msg166275 - (view) |
Author: andrea bergamini (andrea.bergamini) |
Date: 2012-07-24 10:57 |
math.pow(43, 10) gives the wrong result: 21611482313284248.0
Instead, the build-in function 43**10 and pow(43, 10) give the correct result: 21611482313284249L.
This bug has been seen on ActivePython 2.5.1.1. Sorry no tests on recent versions.
|
msg166277 - (view) |
Author: Ezio Melotti (ezio.melotti) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2012-07-24 11:32 |
This is what I get on both 2.7 and 3.3:
>>> import math
>>> math.pow(43, 10)
2.161148231328425e+16
>>> pow(43, 10)
21611482313284249
>>> 43**10
21611482313284249
>>> int(math.pow(43, 10))
21611482313284248
|
msg166278 - (view) |
Author: Serhiy Storchaka (serhiy.storchaka) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2012-07-24 11:42 |
>>> (43**10).bit_length()
55
>>> sys.float_info.mant_dig
53
See http://docs.python.org/faq/design.html#why-are-floating-point-calculations-so-inaccurate
|
msg166283 - (view) |
Author: andrea bergamini (andrea.bergamini) |
Date: 2012-07-24 12:18 |
Ok, but math.pow IMPO has to be aligned to pow and built-in pow (**), otherwise this kind of "inaccuracies" can compromise the application behavior. I was using this funcion in a cryptographic mechanisms, and this issue resulted in a failure.
Generally speaking, integer numbers should not be affected by inaccuracies. I mean, there's no floating point.
|
msg166284 - (view) |
Author: R. David Murray (r.david.murray) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2012-07-24 12:30 |
If I understand correctly, the math module is providing C standard (Annex F) *floating point* mathematical functions. Mark will have the definitive answer once he gets a chance to comment. Perhaps a documentation clarification is in order on this point.
|
msg166285 - (view) |
Author: Stefan Krah (skrah) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2012-07-24 12:38 |
I think Serhiy has already explained that 43**10 is too large
to be represented exactly in 53-bit floating point arithmetic.
The math module wraps the floating point functions from the
C standard:
"It provides access to the mathematical functions defined by the C standard."
"Except when explicitly noted otherwise, all return values are floats."
So there's no bug, and the documentation looks fine to me, too.
|
msg166286 - (view) |
Author: Antoine Pitrou (pitrou) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2012-07-24 12:39 |
Well, the math.pow() doc could use a "seealso" pointing to the built-in pow() function perhaps.
|
msg166287 - (view) |
Author: Stefan Krah (skrah) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2012-07-24 12:45 |
How about changing the title to something like:
math -- 53-bit floating point arithmetic
|
msg166288 - (view) |
Author: Stefan Krah (skrah) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2012-07-24 12:46 |
"Title" referring to the section header of http://docs.python.org/dev/library/math.html ...
|
msg166289 - (view) |
Author: Antoine Pitrou (pitrou) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2012-07-24 12:53 |
That could help, but you easily miss the title when looking up the doc for a given function.
And since log2() already has a seealso for the corresponding int method, pow() could grow one as well.
(and in all honesty I don't know the difference between the "**" operator and the built-in pow() function :-))
|
msg166290 - (view) |
Author: andrea bergamini (andrea.bergamini) |
Date: 2012-07-24 13:02 |
Well, from a library I'm used to expect a good result or an exception. Not a value that differs from the correct of one unit! I agree with Antoine, the doc should warn about this behavior. I've lost a lot of time before discovering my application issue came from the py math library...
|
msg166293 - (view) |
Author: R. David Murray (r.david.murray) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2012-07-24 13:49 |
Your problems didn't come from the "Python" math library, it came from the C math library that Python provides a wrapper for, which the documentation does clearly state. And the result you got is accurate...for a floating point calculation.
|
msg166337 - (view) |
Author: Raymond Hettinger (rhettinger) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2012-07-24 23:18 |
The math module is primarily about exposing the C floating point library functions. Any integer arguments are converted to double.
We could add more docs but that usually doesn't help someone who already has an expectation that math.pow does the same thing as int ** int.
|
msg166370 - (view) |
Author: Mark Dickinson (mark.dickinson) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2012-07-25 08:59 |
Agreed that this is at worst a doc issue.
[Antoine]
> and in all honesty I don't know the difference between the "**" operator
> and the built-in pow() function :-)
None, as far as I know, apart from the pow function's ability to take a 3rd argument. Both ultimately call PyNumber_Power, and the various type-specific __pow__ methods take over from there. [+1 for removing pow from the builtins and shunting three-argument pow to the math module in Python 5000000.]
|
msg166398 - (view) |
Author: Ramchandra Apte (Ramchandra Apte) * |
Date: 2012-07-25 13:46 |
> [+1 for removing pow from the builtins and shunting three-argument pow to the math module in Python 5000000.]
Me too.
Anybody who uses pow with to arguments can use arg1**arg2
Anybody who uses pow with three is doing something mathematical and has most likely imported math already.
|
msg166402 - (view) |
Author: Stefan Krah (skrah) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2012-07-25 14:03 |
Ramchandra Apte <report@bugs.python.org> wrote:
> > [+1 for removing pow from the builtins and shunting three-argument pow to the math module in Python 5000000.]
> Anybody who uses pow with three is doing something mathematical and has most likely imported math already.
Wouldn't that reinforce the misconception that math is for arbitrary precision
number theoretical functions? The OP used it for cryptography.
|
msg166403 - (view) |
Author: Mark Dickinson (mark.dickinson) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2012-07-25 14:13 |
> Wouldn't that reinforce the misconception that math is for arbitrary
> precision number theoretical functions?
Perhaps. We already have math.factorial, though; adding math.powmod wouldn't seem so much of a stretch. Just to be clear, I'm not seriously proposing this for any version of Python before 4.0; apologies for derailing the issue thread.
|
msg166476 - (view) |
Author: andrea bergamini (andrea.bergamini) |
Date: 2012-07-26 12:29 |
Ok guys, ticket closed, but I'm still confused: I'm not a Python expert, I've understood that math is a sort of wrapper of C math.h or something like this, but:
- I can't find any reason in using math.pow if I can get errors like the one explained.
- I've used math.h in my C++ code without having experienced any problem in that pow operation.
I'm surely missing something but I'm a bit confused...
|
msg166478 - (view) |
Author: Serhiy Storchaka (serhiy.storchaka) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2012-07-26 12:52 |
> - I can't find any reason in using math.pow if I can get errors like the one explained.
The reason is your intention to get the error.
>>> pow(-1, 0.5)
(6.123031769111886e-17+1j)
>>> math.pow(-1, 0.5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: math domain error
> - I've used math.h in my C++ code without having experienced any problem in that pow operation.
What you get in C++ as result of pow(43, 10)?
Technically, in C++ you should use <cmath> header, not <math.h>.
|
msg166479 - (view) |
Author: Mark Dickinson (mark.dickinson) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2012-07-26 12:56 |
- I can't find any reason in using math.pow if I can get errors like the one explained.
Yep---don't use math.pow if you want *exact* integer results. If you're doing numerical calculations and errors of around 1 part in 1 thousand million million are acceptable to you, then math.pow works just fine. Just like the other math functions (math.log, math.exp, math.sin, etc.), it's using floating-point arithmetic, so converts its inputs to float and gives a float result. Unlike Python ints, which have unbounded precision, Python floats have a fixed size (64 bits), so there are only finitely many values (less than 2**64) that can be represented exactly. The fact is that the number you were expecting, 21611482313284249, isn't one of those numbers: it *doesn't exist* as a float, because it's not exactly representable in the usual 64-bit floating-point type that Python uses internally.
- I've used math.h in my C++ code without having experienced any problem in that pow operation.
I'd be quite surprised if this were true: if you're using the double type with C or C++, and the pow function from math.h / cmath, you should expect to see *exactly* the same issues. With the 'long double' type, you may get a little more precision (depending on the platform), but that just delays the point at which those issues would appear.
By the way, don't close the issue just yet! There's still ongoing discussion here about whether
there's potential for a documentation improvement.
|
msg166493 - (view) |
Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2012-07-26 16:48 |
C comparison rules are different from Python's.
In the program below (which outputs 1), the mixed comparison will first convert the literal to a double, and lost some precision.
Python does the opposite: the (imprecise) float is converted to a long, so all digits are compared.
#include <math.h>
#include <stdio.h>
int main()
{
printf("result: %d\n", (pow(43,10) == 21611482313284249));
}
|
msg166504 - (view) |
Author: Mark Dickinson (mark.dickinson) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2012-07-26 19:33 |
Ah yes; a comparison like that could indeed give the impression that C/C++ was computing things exactly. :-)
|
msg166693 - (view) |
Author: Antoine Pitrou (pitrou) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2012-07-28 21:08 |
Changing the incredible issue title :-)
|
msg179317 - (view) |
Author: Ezio Melotti (ezio.melotti) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2013-01-08 07:17 |
> Well, the math.pow() doc could use a "seealso" pointing to the built-in
> pow() function perhaps.
Pointing to ``**`` is probably better.
I think that a simple note that mentions the ** operator and when it's better to use it (and possibly the limitations of math.pow) is enough.
Anyone wants to suggest a specific wording?
|
msg180760 - (view) |
Author: Mark Dickinson (mark.dickinson) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2013-01-27 10:48 |
> Anyone wants to suggest a specific wording?
How about the attached patch?
|
msg180773 - (view) |
Author: R. David Murray (r.david.murray) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2013-01-27 15:34 |
I don't think it should be .. note, but otherwise it looks fine to me.
|
msg181835 - (view) |
Author: Mark Dickinson (mark.dickinson) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2013-02-10 18:35 |
Updated patch. Thanks Ezio and David for reviewing.
|
msg181836 - (view) |
Author: Mark Dickinson (mark.dickinson) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2013-02-10 18:36 |
Whoops. Removing a bonus non-grammatical 'function'.
|
msg182233 - (view) |
Author: Ezio Melotti (ezio.melotti) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2013-02-16 17:33 |
LGTM.
(Maybe build the doc and double check that all the links are correct before committing.)
|
msg182708 - (view) |
Author: Roundup Robot (python-dev) ![Python triager (Python triager)](@@file/triager.png) |
Date: 2013-02-23 02:56 |
New changeset ad0712f4b3e0 by Ezio Melotti in branch '2.7':
#15438: add a note to math.pow() that suggests using **/pow() for integers. Patch by Mark Dickinson.
http://hg.python.org/cpython/rev/ad0712f4b3e0
New changeset 7d95a0aa6b5a by Ezio Melotti in branch '3.2':
#15438: add a note to math.pow() that suggests using **/pow() for integers. Patch by Mark Dickinson.
http://hg.python.org/cpython/rev/7d95a0aa6b5a
New changeset a305901366a6 by Ezio Melotti in branch '3.3':
#15438: merge with 3.2.
http://hg.python.org/cpython/rev/a305901366a6
New changeset e0f940829eb6 by Ezio Melotti in branch 'default':
#15438: merge with 3.3.
http://hg.python.org/cpython/rev/e0f940829eb6
|
msg182744 - (view) |
Author: Mark Dickinson (mark.dickinson) * ![Python committer (Python committer)](@@file/committer.png) |
Date: 2013-02-23 13:59 |
Thanks, Ezio; I didn't get around to dealing with this as quickly as I meant to.
|
|
Date |
User |
Action |
Args |
2022-04-11 14:57:33 | admin | set | github: 59643 |
2013-02-23 13:59:12 | mark.dickinson | set | messages:
+ msg182744 |
2013-02-23 02:56:51 | ezio.melotti | set | status: open -> closed resolution: fixed stage: commit review -> resolved |
2013-02-23 02:56:03 | python-dev | set | nosy:
+ python-dev messages:
+ msg182708
|
2013-02-16 17:33:05 | ezio.melotti | set | messages:
+ msg182233 stage: needs patch -> commit review |
2013-02-10 18:36:42 | mark.dickinson | set | files:
+ issue15438_3.patch
messages:
+ msg181836 |
2013-02-10 18:35:29 | mark.dickinson | set | priority: low -> normal assignee: mark.dickinson messages:
+ msg181835
files:
+ issue15438_2.patch |
2013-01-27 15:34:55 | r.david.murray | set | messages:
+ msg180773 |
2013-01-27 10:48:36 | mark.dickinson | set | files:
+ issue15438.patch keywords:
+ patch messages:
+ msg180760
|
2013-01-08 07:17:14 | ezio.melotti | set | versions:
+ Python 2.7, Python 3.2, Python 3.3, Python 3.4 resolution: not a bug -> (no value) messages:
+ msg179317
assignee: rhettinger -> (no value) type: behavior -> enhancement stage: needs patch |
2013-01-07 16:27:15 | serhiy.storchaka | set | nosy:
- serhiy.storchaka
|
2012-07-28 21:08:20 | pitrou | set | messages:
+ msg166693 title: Incredible issue in math.pow -> document that math.pow is inappropriate for integers |
2012-07-26 19:33:35 | mark.dickinson | set | messages:
+ msg166504 |
2012-07-26 16:48:36 | amaury.forgeotdarc | set | nosy:
+ amaury.forgeotdarc messages:
+ msg166493
|
2012-07-26 12:56:19 | mark.dickinson | set | status: closed -> open
messages:
+ msg166479 |
2012-07-26 12:52:59 | serhiy.storchaka | set | messages:
+ msg166478 |
2012-07-26 12:29:54 | andrea.bergamini | set | status: open -> closed
messages:
+ msg166476 |
2012-07-25 14:13:10 | mark.dickinson | set | messages:
+ msg166403 |
2012-07-25 14:03:26 | skrah | set | messages:
+ msg166402 |
2012-07-25 13:46:33 | Ramchandra Apte | set | nosy:
+ Ramchandra Apte messages:
+ msg166398
|
2012-07-25 08:59:07 | mark.dickinson | set | messages:
+ msg166370 |
2012-07-24 23:18:41 | rhettinger | set | resolution: not a bug components:
+ Documentation, - Library (Lib) |
2012-07-24 23:18:15 | rhettinger | set | priority: normal -> low
nosy:
+ rhettinger messages:
+ msg166337
assignee: rhettinger |
2012-07-24 13:49:28 | r.david.murray | set | messages:
+ msg166293 |
2012-07-24 13:02:50 | andrea.bergamini | set | messages:
+ msg166290 |
2012-07-24 12:53:20 | pitrou | set | messages:
+ msg166289 |
2012-07-24 12:46:17 | skrah | set | messages:
+ msg166288 |
2012-07-24 12:45:06 | skrah | set | messages:
+ msg166287 |
2012-07-24 12:39:59 | pitrou | set | nosy:
+ pitrou messages:
+ msg166286
|
2012-07-24 12:38:19 | skrah | set | messages:
+ msg166285 |
2012-07-24 12:30:30 | r.david.murray | set | nosy:
+ r.david.murray messages:
+ msg166284
|
2012-07-24 12:18:41 | andrea.bergamini | set | messages:
+ msg166283 |
2012-07-24 11:42:46 | serhiy.storchaka | set | nosy:
+ serhiy.storchaka messages:
+ msg166278
|
2012-07-24 11:32:57 | ezio.melotti | set | nosy:
+ skrah, ezio.melotti messages:
+ msg166277
|
2012-07-24 11:08:12 | ned.deily | set | nosy:
+ mark.dickinson
|
2012-07-24 10:57:49 | andrea.bergamini | create | |