[issue47031] math.nan should note that NANs do not compare equal to anything
New submission from Steven D'Aprano <steve+python@pearwood.info>: The IEEE-754 requirement that NANs are never equal to anything, even to themselves, is a common stumbling block for those new to the consequences of IEEE-754. See for example #47020. The documentation for math.nan would be a good place to add a note like "Due to the requirements of the `IEEE-754 standard <https://en.wikipedia.org/wiki/IEEE_754>`_, math.nan and float('nan') are never equal to any other value, including themselves. Use math.isnan to test for NANs." https://docs.python.org/3.8/library/math.html#math.nan ---------- assignee: docs@python components: Documentation keywords: easy messages: 415302 nosy: docs@python, steven.daprano priority: normal severity: normal status: open title: math.nan should note that NANs do not compare equal to anything type: enhancement versions: Python 3.10, Python 3.11, Python 3.7, Python 3.8, Python 3.9 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue47031> _______________________________________
Stanley <ostanley.lee@gmail.com> added the comment: How does this sound instead? The unequalness is pushed to the front and the IEEE part back so it's less likely missed: Math.nan and float('nan') are never equal to any other value, including themselves, as per IEEE 754. Use math.isnan to test for NANs. ---------- nosy: +slateny _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue47031> _______________________________________
Vedran Čačić <vedgar@gmail.com> added the comment: I'm not satisfied with "and" formulation. For all practical purposes, math.nan is the "same" object as float('nan'), they just represent two ways of referring to it (or constructing it). To me it sounds a bit like "2 and 1+1 are the only even prime numbers." I suggest the docs only speak of math.nan here, and elsewhere to say that they can also be constructed by float('nan'). ---------- nosy: +veky _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue47031> _______________________________________
Serhiy Storchaka <storchaka+cpython@gmail.com> added the comment: We cannot guarantee that NAN never equal to anything, because we can create an object equal to it. For example mock.ANY. ---------- nosy: +serhiy.storchaka _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue47031> _______________________________________
Stanley <ostanley.lee@gmail.com> added the comment: Vedran's got a good point, as existing documentation for math.nan already says "... Equivalent to the output of float('nan')." so it does seem a bit redundant to say both, though I wonder if we should still be explicit since
import math math.nan is math.nan True float('nan') is float('nan') False
so they don't have the exact same behavior. Serhiy also has a good point, so maybe instead say that Math.nan/float('nan') is *generally* not equal to any other value? ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue47031> _______________________________________
Charlie Zhao <zhaoyu_hit@qq.com> added the comment:
"Due to the requirements of the `IEEE-754 standard <https://en.wikipedia.org/wiki/IEEE_754>`_, math.nan and float('nan') are never equal to any other value, including themselves. Use math.isnan to test for NANs."
It seems to me, Steven's description is clear enough to tell us that "Be careful if you want to compare NANs with others". One thing to emphasize is that neither `is` nor `==` is a best practice, just like slateny's example, we should be wary of the difference between `float('nan')` and `math.nan`. Adding an example to the docs would be a good way to let everyone know the difference and use `math.isnan` instead of `is` and `==` to test for NANs. ---------- nosy: +CharlieZhao _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue47031> _______________________________________
Steven D'Aprano <steve+python@pearwood.info> added the comment:
We cannot guarantee that NAN never equal to anything, because we can create an object equal to it. For example mock.ANY
Sure. I don't expect that mock.ANY or other weird objects should obey the IEEE-754 rules. But we're talking numeric comparisons here, not arbitrary objects which may do arbitrary things in their `__eq__` method. The documentation for the math module assumes we're talking about sensible, standard numeric values that don't play strange tricks on the caller. Look at the first function documented: math.ceil(x) Return the ceiling of x, the smallest integer greater than or equal to x. If x is not a float, delegates to x.__ceil__(), which should return an Integral value. class MyWeirdFloat(float): def __ceil__(self): return -1 math.ceil(MyWeirdFloat(25.9)) # Returns -1 instead of the ceiling. Does the documentation really need to cover every imaginable weird class? I don't think so. Let's keep it simple. NANs compared unequal with all numeric values which directly or indirectly obey IEEE-754, which includes floats. ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue47031> _______________________________________
Stanley <ostanley.lee@gmail.com> added the comment: Then perhaps saying that it's *never* equal is too strong, and instead we just say it's *not* equal. Not too sure how to phrase the behavior difference between `==` and `is` though, if that's something that should be noted. ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue47031> _______________________________________
Change by Charlie Zhao <zhaoyu_hit@qq.com>: ---------- keywords: +patch pull_requests: +30248 stage: -> patch review pull_request: https://github.com/python/cpython/pull/32170 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue47031> _______________________________________
Charlie Zhao <zhaoyu_hit@qq.com> added the comment: I started a PR and some simple examples were added. It is helpful for those who are new to IEEE-754. According to Jelle's comments, the behavior of `float('nan') is float('nan')` may be changed in the future, so I just omit it and suggest users to use `math.isnan()`. This might make the documentation a bit clearer. ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue47031> _______________________________________
Jelle Zijlstra <jelle.zijlstra@gmail.com> added the comment: New changeset 182e93c3f57b0c72e765c9896066d32e461c0865 by Charlie Zhao in branch 'main': bpo-47031: Improve documentation for `math.nan` (GH-32170) https://github.com/python/cpython/commit/182e93c3f57b0c72e765c9896066d32e461... ---------- nosy: +JelleZijlstra _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue47031> _______________________________________
Change by miss-islington <mariatta.wijaya+miss-islington@gmail.com>: ---------- nosy: +miss-islington nosy_count: 7.0 -> 8.0 pull_requests: +30328 pull_request: https://github.com/python/cpython/pull/32263 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue47031> _______________________________________
Change by miss-islington <mariatta.wijaya+miss-islington@gmail.com>: ---------- pull_requests: +30329 pull_request: https://github.com/python/cpython/pull/32264 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue47031> _______________________________________
miss-islington <mariatta.wijaya+miss-islington@gmail.com> added the comment: New changeset 319a70cf99c9866c7fa47deecf04f6ebcfe35a54 by Miss Islington (bot) in branch '3.10': bpo-47031: Improve documentation for `math.nan` (GH-32170) https://github.com/python/cpython/commit/319a70cf99c9866c7fa47deecf04f6ebcfe... ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue47031> _______________________________________
miss-islington <mariatta.wijaya+miss-islington@gmail.com> added the comment: New changeset 5b80031fb0d2ea14f0d42a33309ce5464c4a6042 by Miss Islington (bot) in branch '3.9': bpo-47031: Improve documentation for `math.nan` (GH-32170) https://github.com/python/cpython/commit/5b80031fb0d2ea14f0d42a33309ce5464c4... ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue47031> _______________________________________
Jelle Zijlstra <jelle.zijlstra@gmail.com> added the comment: Thanks for the bug report and patch! ---------- resolution: -> fixed stage: patch review -> resolved status: open -> closed _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue47031> _______________________________________
participants (7)
-
Charlie Zhao
-
Jelle Zijlstra
-
miss-islington
-
Serhiy Storchaka
-
Stanley
-
Steven D'Aprano
-
Vedran Čačić