Could someone specifically explain why the last digit is 5 instead of 2 or 4? Knowing a float must have an inaccuracy in the binary world, I can't get exactly how the result of the case above has been made in detail.
-
7Read carefully, folks. This isn't the standard "why is this floating point result inaccurate" question. It's more specific: why is the error more than +/-1 in the last digit? – John Kugelman Dec 17 '16 at 02:54
-
1@JohnKugelman Because binary representation of the number, which seems to be addressed in the other post. Is that not correct? – OneCricketeer Dec 17 '16 at 03:06
-
3@cricket_007: "Because binary", while accurate in a certain sense, is missing too many logical steps for it to qualify as a real explanation. The questioner already knows that floats are binary. – user2357112 Dec 17 '16 at 03:20
-
ObLink: [What Every Computer Scientist Should Know About Floating-Point Arithmetic](https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html). And there's lots of good info in the answers to [Is floating point math broken?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) – PM 2Ring Dec 17 '16 at 07:15
2 Answers
It's because it's the closest a (64bit) float
can be to the "true value" of 10/3
.
I use cython here (to wrap math.h nexttoward
function) because I don't know any builtin function for this:
%load_ext cython
%%cython
cdef extern from "<math.h>" nogil:
# A function that get's the next representable float for the
# first argument in direction to the second argument.
double nexttoward(double, long double)
def next_float_toward(double i, long double j):
return nexttoward(i, j)
(or as pointed out by @DSM you could also use numpy.nextafter
)
When I display the values for 10/3
and the previous and next representable float for this value I get:
>>> '{:.50}'.format(10/3)
3.3333333333333334813630699500208720564842224121094
>>> '{:.50}'.format(next_float_toward(10/3., 0))
3.3333333333333330372738600999582558870315551757812
>>> '{:.50}'.format(next_float_toward(10/3., 10))
3.3333333333333339254522798000834882259368896484375
So each other representable floating point value is "further" away.

- 145,886
- 38
- 333
- 352
-
1I don't know any built-in function either, but `np.nextafter` is probably simpler.. (although in the answer I was working on I just used `.hex()` and `float.fromhex` to build it manually.) – DSM Dec 17 '16 at 03:20
Because the largest representable value smaller than ...335 is ...330 (specifically, it's smaller by 2**-51
, or one Unit in the Last Place). ...333 is closer to ...335 than it is to ...330, so this is the best possible rounding.
There are a number of ways to confirm this; MSeifert shows one thing you can do directly with <math.h>
from C or Cython. You can also use this visualization tool (found by Googling "floating point representation" and picking one of the top results) to play with the binary representation.

- 28,963
- 9
- 62
- 81