In a world of humans and finance, it’s quite common to need base10
logarithms. (Yay for Math.log10!)
In a world of computers, it’s also quite common to need base2
logarithms. Ruby only gives you ‘natural’ logarithms in the form of
Math.log. (Bummer.)
It has probably been more than 5 times that I’ve had to look up the
formula to discover than
logbasen(x) == logbasewhatever(x) / logbasewhatever(n)
I was reminded by it when Martin had to write his own log2 function to
answer my previous question.
Is there any objection to me proposing to add both:
Math.log2(x)  base2 logarithm
Math.logn(x,n)  basen logarithm
directly to the core of Ruby?
Ideally they’d be implemented in C, but of course the simple Ruby
implementation is just:
def Math.log2( x ); Math.log( x ) / Math.log( 2 ); end
def Math.logn( x, n ); Math.log( x ) / Math.log( n ); end
Since they’re so simple, I’m almost hesitant to ask for them in
core…except that they’ve cropped up for me again and again, and it
always takes me a while to hunt them down. Languages like Lua thrive
on simplicity of implementation. I think Ruby thrives on the richness
of the immediatelyavailable methods in core and stdlib. I feel these
are common enough to deserve general inclusion.
Ideally they’d be implemented in C, but of course the simple Ruby
implementation is just:
def Math.log2( x ); Math.log( x ) / Math.log( 2 ); end
def Math.logn( x, n ); Math.log( x ) / Math.log( n ); end
I second the motion.
The log2 function is now in the C math library, so I think it would
easy to add it the Ruby Math library. I would like see log for
arbitrary base added too. But here I would suggest a slightly
different name and argument order:
def Math.logb(b, x); Math.log(x) / Math.log(b); end
This, I believe, would be more in accord with other programming
languages that already offer this function.
Other than changing the order of parameters (which I’m personally
ambivalent about, and would certainly accept this order if that’s how
most other libraries do it) and changing the name to end in an
underscore (which I’m not sure I like), what are you proposing that I
wasn’t? Simply that we ONLY add the logbasen capability that I
described, without a specific method for logbase2 calculations?
ambivalent about, and would certainly accept this order if that’s how
most other libraries do it) and changing the name to end in an
underscore (which I’m not sure I like), what are you proposing that I
wasn’t? Simply that we ONLY add the logbasen capability that I
described, without a specific method for logbase2 calculations?
Well, I can find examples with the base first or second. Perhaps for
Ruby it would most idiomatic to define log as follows
def Math.log(x, b=Math::E); ... ; end
as the core method with log10 and log2 handled (for performance) as
special cases within this method. Given that, I would still want Math
to implement log10 and log2 methods for convenience.
If we were to go with a two argument log, I prefer the “logb” name to
“logn” because “n” suggests an integer and the base doesn’t have to
be an integer (e.g., it could be Math::E).
Well, I can find examples with the base first or second. Perhaps for
Ruby it would most idiomatic to define log as follows
def Math.log(x, b=Math::E); ... ; end
as the core method with log10 and log2 handled (for performance) as
special cases within this method. Given that, I would still want Math
to implement log10 and log2 methods for convenience.
Math.log calls the log in the standard math library, which I suspect
implements the natural log calculation pretty efficiently. If you
make the second parameter the base, you’ll either have to check it
against Math::E and treat it as a special case or do two log
calculations for the natural log case. I don’t like either of those
options.
In message “Re: Adding Math.log2 and Math.logn to the core library.”
on Thu, 8 Feb 2007 09:08:38 +0900, Morton G. [email protected] writes:
Well, I can find examples with the base first or second. Perhaps for
Ruby it would most idiomatic to define log as follows

 def Math.log(x, b=Math::E); … ; end
Math.log calls the log in the standard math library, which I suspect
implements the natural log calculation pretty efficiently. If you
make the second parameter the base, you’ll either have to check it
against Math::E and treat it as a special case or do two log
calculations for the natural log case. I don’t like either of those
options.
If there’s too much of a performance penalty for this, I would have
no problem with the general case being implemented under a different
name, and I would suggest “logb” – that is,
def Math.logb(x, b=Math::E); ... ; end
My main point is that I think the general case should default its
base to Math::E. If we were to end up with Math.log (alias Math.ln),
Math.log10, Math.log2, and Math.logb (the general case) that would
be fine.
Regards, Morton
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.