msg91886 - (view) |
Author: Steve (steve21) |
Date: 2009-08-23 11:56 |
$ python3.1 Python 3.1 (r31:73572, Jul 6 2009, 21:21:12) [GCC 4.4.0 20090506 (Red Hat 4.4.0-4)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import math >>> math.log10(1000) 3.0 >>> math.log(1000, 10) 2.9999999999999996 You would expect the results to be the same. Internally math.log() could call math.log10() when base==10. That would ensure they are consistent. |
|
|
msg91888 - (view) |
Author: Mark Dickinson (mark.dickinson) *  |
Date: 2009-08-23 15:22 |
Well, that's floating-point arithmetic for you. log(x, y) simply computes log(x)/log(y) behind the scenes; since both log computations and the floating-point division can introduce errors, the result will frequently not be correctly rounded. I don't really see the benefit of special-casing log(x, 10). In what circumstances does it matter that log(x, 10) != log10(x)? I could understand people being upset that log(10**n, 10) doesn't return n exactly, but that's what log10 is there for. See also the discussion in issue 3724. |
|
|
msg91900 - (view) |
Author: Steve (steve21) |
Date: 2009-08-24 02:04 |
Mark, "... that's what log10 is there for". That would be a good point if the documentation said that. However, all the docs for log10 say is: math.log10(x) Return the base-10 logarithm of x. So we have a python function log10() which looks like it is redundant since we can use log(a, 10) instead. But it actually functions differently to log(a, 10), and the Python user would never know this from looking at the documentation. I think Tim Peters missed one important guideline in his "The Zen of Python". The principle of least astonishment (or surprise) - when two elements of an interface conflict, or are ambiguous, the behaviour should be that which will least surprise the human user or programmer at the time the conflict arises. Its easy for the python developer to ignore this guideline. They know the implementation, and are rarely surprised by inconsistent behaviour since they have seen it before, or even created it without documenting it. If Python functions are inconsistent then I think they should either be made consistent, or if that's not possible they should be clearly documented as being inconsistent. The docs for log(x[, base]) could be improved to say: "this function preserves the consistency of log(a,b) == log(a)/log(b) but breaks consistency with log(a,10) == log10(a)" The docs for log10(x) could be improved to say: "this function gives the correct result for powers of 10, but breaks consistency with log(a,10) == log10(a)" |
|
|
msg91918 - (view) |
Author: Mark Dickinson (mark.dickinson) *  |
Date: 2009-08-24 13:09 |
> If Python functions are inconsistent then I think they should either be > made consistent, or if that's not possible they should be clearly > documented as being inconsistent. I think 'inconsistent' is a bit strong for what happens here. In my view, the expressions log10(x) and log(x, 10) behave consistently: they both give (good) floating-point approximations to the base-10 logarithm of x. However, since they use slightly different methods to get those approximations, the approximations are not identical. Would you also say that atan2(y, x) is inconsistent with atan(y/x) (for positive x, y, say), because they give minutely different results in some cases? > The docs for log10(x) could be improved to say: > "this function gives the correct result for powers of 10, > but breaks consistency with log(a,10) == log10(a)" I find this unnecessarily negative. I propose instead to leave the log documentation as it is, and add something like the following to the log10 documentation, as an explanation of why log10 is still valuable in the presence of the two-argument log function: """Since this function directly wraps the platform log10 function, ``log10(x)`` will usually (depending on the platform) be faster and more accurate than the mathematically equivalent ``log(x, 10)``.""" Note that historically, the two-argument version of math.log appeared long after math.log10 did; this might help explain the apparent redundancy. (I'd actually argue that the two-argument log should not have been added in the first place: it doesn't wrap a standard C math function, and it's really no different from log(x)/log(y), except that having it as a built-in library function gives the illusion that it might be more accurate than it actually is. However, that's academic now.) One possible 'fix' for this situation does occur to me: instead of computing log(x, y) internally as log(x)/log(y), compute it as log10(x)/log10(y). This at least doesn't involve extensive changes or additions to the code. I don't think it really makes any practical difference, except perhaps in reducing the number of bug reports like this one. And it won't help make log2(x) == log(x, 2) if/when the C99 log2 function is added to the math library, either. I'd be -0 on making this change. |
|
|
msg91919 - (view) |
Author: Tim Peters (tim.peters) *  |
Date: 2009-08-24 13:25 |
I wasn't keen to add the 2-argument log() extension either. However, I bet it would help if the docs for that were changed to explain that log(x, base) is just a convenient shorthand for computing log(x)/log(base), and therefore may be a little less accurate than a function that directly computed the logarithm wrt the given base. |
|
|
msg92042 - (view) |
Author: Terry J. Reedy (terry.reedy) *  |
Date: 2009-08-28 20:11 |
Reopening as doc issue. This is at least the second time this issue has been reported (see #3724), with some agreement on doc tweak, but not done. Specific suggestions for math module doc, 9.2.2: math.log(x[, base]) Return the logarithm of x to the given base. add: ", calculated as log(x)/log(base)" before period. [This could be removed if better method ever implemented.] math.log10(x) Return the base-10 logarithm of x. add: "This is usually more accurate than log(x, 10)." |
|
|
msg92126 - (view) |
Author: Georg Brandl (georg.brandl) *  |
Date: 2009-09-01 07:54 |
Okay, I made changes along Terry' suggestions in r74617. |
|
|