Adding to numpy.nextafter() float returns unexpected result
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Dreaming in Puzzles
--
Chapters
00:00 Adding To Numpy.Nextafter() Float Returns Unexpected Result
00:34 Accepted Answer Score 8
01:35 Answer 2 Score 3
02:09 Thank you
--
Full question
https://stackoverflow.com/questions/1354...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #numpy #python27 #ieee754
#avk47
ACCEPTED ANSWER
Score 8
import numpy as np
x = 2.0
while True:
if 6.0/(x+16) > 2.0/(x+4): break
x = np.nextafter(x, x+1)
print(repr(x))
yields
2.0000000000000009
How floats are handled in CPython depends on the underlying C library. Most C libraries implement the IEEE 754 Standard for Floating-Point Arithmetic. However, "the IEEE standard does not guarantee that the same program will deliver identical results on all conforming systems." (See p. 249 of "What Every Computer Scientist Should Know about Floating-Point Arithmetic" (PDF) and also PEP 754).
To be able to predict the value x without iteration, one would have to study how floating point arithmetic is done (ibid (PDF)), write down x in its general binary format,

substitute this into the inequality
6.0/(x+16) > 2.0/(x+4)
and trace through the floating point arithmetic algorithms to solve for the digits dᵢ corresponding to the smallest float that satisifies the inequality.
ANSWER 2
Score 3
unutbu's method should be pretty general. If what you're asking for is why it doesn't work after the first iteration, the answer is because of rounding. When you use np.nextafter, you're working at the limit of precision, so any arithmetic operation after that can't be trusted implicitly. In your case, it's probably the + 16 that's the problem. 16 is a couple exponent bits up from 2, so you're going to lose that increment to finite precision. In this case, it takes one extra increment to get that sum to round up instead of down.