int(0.99999999999999999) == 1. Why exactly is that? | SoloLearn: Learn to code for FREE!

+26

int(0.99999999999999999) == 1. Why exactly is that?

In most cases, when you int a float (or in C when you (int) a double), the effect seems to be that the decimals are just 'cut off'. Funnily, this is not always true: In the given example, the result will be 1. What exactly is going on? I have figured out that it happens just beyond the precision cutoff point. So a double with 16 nines as decimals will be 'floored', add one more, and it will be 'ceiled'. For floats, the borderline is 7/8. Can someone explain, and in a way that doesn't necessitate deeply understanding all the hardware intricacies of doubles and floats?

1/28/2020 10:40:40 AM

HonFu

62 Answers

New Answer

+49

x=0.99999... 10x=9.999... 10x=9+0.9999... 10x=9+x 9x=9 x=1 Source: https://en.wikipedia.org/wiki/0.999... Not sure if in programming happens the same but i am impressed.

+26

From what I have read 0.99999999999999999 is a double precision number that is too precise to be represented accurately in 64 bits and the next most accurate representation is 1.0 hence the value is rounded up. from last digit as 5 and above it will be rounded up to 1.0

+16

~ swim ~, I wonder how this 'too precise is precisely determined. Does a double know the places after the 16th? Wouldn't it have to know in order where to round to? Wouldn't it need precision for this in the first place? I just tried what you said. 0.99999999999999995 becomes 1, but 0.99999999999999994 becomes 0. If we add another digit, this pattern seems to repeat: 0.999999999999999945 becomes 1, while 0.999999999999999944 becomes 0. 🤔

+15

blackwinter that's a mathematical answer but doesn't explain why there is a precision cut off point.

+13

blackwinter, now I'm not sure anymore, would the double specifics be easier to master? 😂 I've read about half of it, but somehow my brain can't get past the '0.9999 == 1 - wait what?' point yet. I guess I'm a case of the 'education problem' they mention... 🤔

+13

I did some research for Python. Hope it helps. Thou official documentation is uncertain. https://code.sololearn.com/cj9eYbj65J8J/?ref=app

+12

I agree with ~ swim ~ . In the docs(https://docs.python.org/3/tutorial/floatingpoint.html#tut-fp-issues) it is written - "...so Python keeps the number of digits manageable by displaying a rounded value instead..." So my best *guess* is that after a number exceeds a specific number of bits, python rounds it off. Note: I might be wrong here. This is just my guess.

+9

Hopefully it won't double over. 😂

+8

Awesome discussion. It's good to revisit floating point arithmetic oddities every once and a long while. 🤓 Interestingly, using the Decimal type initialized with equivalent string values of 0.99999999999999999 will overcome the issue of converting to a float with the bits turning over to 1.0. While Decimal type is likely significantly slower than floats, you have greater control over behavior based on precision and rounding contexts. Take a look at these links for more details: https://code.sololearn.com/c9mQEFxn9b07/ https://docs.python.org/3/library/decimal.html

+7

Mihai Apostol, so my suspicion that I can't rely on 'int-truncating' *was* justified after all, even if my provided example was caused by something else, hm?

+6

Sonic, yeah, or why the cutoff doesn't lead to all that decimal being cut off.

+6

The representation of double precision floating point numbers seems to reserve about 52 bits for the precision (I.e. other than for the sign bit and exponent). 2^52 is approximately 4.5*10^15. So 16 figures (including the non fractional part) seems to be the maximum precision that can be stored in a double precision number using the IEEE 754 standard. I guess therefore that any number less than but approaching 1.0 and containing more than 16 digits is going to be rounded up.

+6

Its just an application of david gay's algorithm,called data truncation and approximation,your CPU only understands binary,so in order to do calculations on your CPU, your programming language has to process your inputs into binary,but for numbers like(1/3),representing this in binary could be quite difficult,as (1/3) = 0.3333333333333333333..till infinity,which cannot be properly represented on the CPU about (0.0101010001111010111),in binary..,so David gay's algorithm helps to truncate this by chopping off the least significant digit,which is then round off the to the nearet decimal ,

+6

Seems like there's a simple explanation: Before int() is called the number is first converted into a double. The double represents the most accurate representation of that number which is eventually 1 as you increase the number of nines. And int(1.0) obviously returns 1. https://code.sololearn.com/cBNa2y6Lkoi6/?ref=app

+6

Grappling with infinity is only hard until you decide that it's not by the way. Back in the early calculus days people would say: well, `0.999...` is `1-1/(10^n)`, and the fraction tends to 0, so 0.999... = 1. And they'd call it a day. Then Cauchy came along and gave a formal definition of limits, to make things harder: "You gimme a function `f(n)` and your proposed limit. Prove that the difference between the two is no more than a gap `ε` of my choosing. That is, I give you an `ε`, you find me `n`." iff `f(n) - L < ε` for an arbitrary ε>0, then the limit of `f` is `L`. So because the gap between 0.999... and 1 is arbitrarily small, they may aswell be the same. 0.888... does not tend to 0.9 by the way. I bet you can't find any amount of 8s such that the gap becomes smaller than 0.01. (0.899... does though) (by the way)², never believe in the triple dots "...", they are lying. `0.999...` highjacks your brain into thinking everything is ok, but it's not. What does `0.132...` even mean? Nothing.

+6

We're getting very philosophical 😃. What's wrong with the theory that the IEEE 754 standard for double precision floating point numbers only allows for 53 significand bits and hence 16 significant digits and that any representation containing more digits than that is going to be rounded up? 🙆

+5

You could be perfectly sure instead if you had read just the headline of my original post. Because this was my question to begin with, why this happens.

+4

Mihai Apostol This is actually double type info since python floats are double precision numbers.

+4

Zuke, I have read that argumentation line up there in the Wikipedia link, but it seems still strange to me. We're talking about eternity, right? 9s stretching out forever. I remember from looooong ago when in maths we had curves that would forever try to reach a point, but never really get there. To me, it still looks like a 9 was added over and over, an eternal loop while(n<1) - so forever (in my mind). Whenever I encounter one of these maths topics, I feel like a 6 year old. 😂

+4

~ swim ~, I'm talking about int(0.888...)