classification
Title: math.log(x, 10) gives different result than math.log10(x)
Type: behavior Stage:
Components: Versions: Python 2.6
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: mark.dickinson Nosy List: mark.dickinson, rhettinger, segfaulthunter, terry.reedy, vstinner
Priority: normal Keywords: patch

Created on 2008-08-29 12:32 by segfaulthunter, last changed 2009-09-01 09:58 by terry.reedy. This issue is now closed.

Files
File name Uploaded Description Edit
log.patch segfaulthunter, 2008-08-29 20:31 Internally use math.log10 when math.log gets the base 10 to improve accuracy and performance.
math_doc.patch segfaulthunter, 2008-09-03 21:44 Documentation tweak.
Messages (12)
msg72129 - (view) Author: Florian Mayer (segfaulthunter) Date: 2008-08-29 12:32
I have found out that the result of math.log(x, 10) is slightly more
inaccurate than the one of math.log10(x). Probably the best example is
math.log(1000, 10) and math.log10(1000). I have attached a patch that
forces math.log to internally use log10 when it gets the base 10. Patch
is against revision 66056. Also adds 3 tests to test_math.py to test new
behaviour implemented.
msg72389 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2008-09-03 16:07
I can't really see a compelling reason to make this change---it
seems like an unnecessary complication to add to what's currently
a simple function.  Someone who really needs the accuracy can
just use log10.  Perhaps a note in the documentation for log
suggesting this would be useful.

I guess this solution seems insufficiently general:  why 'fix'
log(x, 10) but not log(x, 2), for example?

OTOH, a two-argument log that was guaranteed correctly rounded
(or accurate to within 1ulp) for *all* bases would certainly
be of interest!  But that's a fairly major project...
msg72398 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2008-09-03 17:00
Mark, thanks for the first review comments.  Am also disturbed by the
lack of generality and don't think it wise to introduce a discontinuity.
 Am rejecting this patch.  Leaving the bug report open in case other
solutions arise.
msg72423 - (view) Author: Florian Mayer (segfaulthunter) Date: 2008-09-03 21:44
Uploaded small documentation patch warning the user of math.log(x, 10)
inaccuracy.
msg74349 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2008-10-05 17:15
Mark, is some of the inaccuracy due to double rounding?  Could we make
the two argument form more accurate by allowing the compiler to generate
code that uses full internal precision, log(n)/log(d), instead of
prematurely forcing the intermediate results to a PyFloat?
msg74578 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2008-10-09 14:25
> Mark, is some of the inaccuracy due to double rounding?

No, I don't think so;  at least, not in the sense of rounding the same 
value twice (with different precisions).  I get similar results on my 
Core 2 Duo machine, which should be immune to x87 style problems 
(because Apple's gcc turns sse instructions on by default, I guess).  
It's just a result of three separate rounds: one for each log, and one 
for the result of the division.

> Could we make the two argument form more accurate by allowing the
> compiler to generate code that uses full internal precision,
> log(n)/log(d), instead of prematurely forcing the intermediate results
> to a PyFloat?

Seems to me that would only work on older x86 hardware, unless we 
deliberately use long double in place of double for the intermediate 
results.

Personally, I don't think it's worth the effort of fixing this:  the 
result of log(x, 10) is accurate to within a few ulps anyway, which 
should be plenty good enough for any well-coded numerical work:  any 
numerically aware programmer should be well aware that it's dangerous to 
rely on floating-point operations giving exact results.

And in any case there's always log10.

As a separate issue, it may be worth exposing C99's log2 function in 
some future version of Python.  This, presumably, can be relied upon 
always to give exact results for powers of 2, which could be useful in 
some applications.
msg74584 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2008-10-09 16:13
+1 on a log2 function, especially one that has been generalized to work
with long integers.  It would help with the "numbits" problem that
comes-up all the time.
msg74630 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2008-10-10 12:08
About large integers which can not be converted to float (too big!): 
it would be nice if math.log2() and/or math.log10() works which such 
numbers. But it would better if you know if the functions used the FPU 
or not (only integers). Idea:
 - logX(int)->int: don't use FPU
 - logX(float)->float: use FPU
 - logX(int)->float: use FPU

What should be the default type for logX(int)? People expects float 
when using logX().

Note: logX() means math.log(), math.log2() and/or math.log10().
msg74734 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2008-10-14 11:59
Note that log2(int) -> float wouldn't entirely replace
numbits, due to loss of precision in the result.

e.g.  log2(2**100), log2(2**100+1) and log2(2**100-1) would likely all
return exactly the same result (100.0), where numbits wants results of 
101, 101 and 100 respectively.
msg74738 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2008-10-14 12:12
About the number of bits: I prefer an the implementation in int/long 
types proposed in issue #3439.
msg77077 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2008-12-05 21:47
I'm closing this, for reasons already given.

For the proposal to add log2, see issue 3366.
msg92139 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2009-09-01 09:58
The docs were patched in r74617 to (re)close #6765.
This included something similar to the OP's math_doc.patch.
History
Date User Action Args
2009-09-01 09:58:50terry.reedysetnosy: + terry.reedy
messages: + msg92139
2008-12-05 21:47:35mark.dickinsonsetstatus: open -> closed
messages: + msg77077
2008-10-14 12:12:42vstinnersetmessages: + msg74738
2008-10-14 11:59:06mark.dickinsonsetmessages: + msg74734
2008-10-10 12:08:36vstinnersetnosy: + vstinner
messages: + msg74630
2008-10-09 16:13:02rhettingersetmessages: + msg74584
2008-10-09 14:25:52mark.dickinsonsetmessages: + msg74578
2008-10-05 17:15:52rhettingersetassignee: rhettinger -> mark.dickinson
messages: + msg74349
2008-09-03 21:58:01rhettingersetassignee: mark.dickinson -> rhettinger
2008-09-03 21:44:46segfaulthuntersetfiles: + math_doc.patch
messages: + msg72423
2008-09-03 17:00:27rhettingersetresolution: rejected
messages: + msg72398
nosy: + rhettinger
2008-09-03 16:08:00mark.dickinsonsetmessages: + msg72389
2008-08-30 13:16:05georg.brandlsetassignee: mark.dickinson
nosy: + mark.dickinson
2008-08-29 20:31:20segfaulthuntersetfiles: + log.patch
2008-08-29 20:29:47segfaulthuntersetfiles: - log.patch
2008-08-29 12:32:07segfaulthuntercreate