-
Notifications
You must be signed in to change notification settings - Fork 1.3k
float -> int unusuallness at 1.0 #230
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
CircuitPython currently does all arithmetic in single-precision, whereas CPython uses double. So I think you're seeing an artifact of that. [EDIT: no, it's something else]
|
yah im going to use round() but i thought it odd that it prints 1.0 even tho it is not 1.0 :) |
I did some more experiments. It does appear that there's something weird with MicroPython floating-point arithmetic or conversion from decimal. In MicroPython/CircuitPython:
In CPython, the difference is I can't duplicate this in C with single-precision:
I have to try hard not to let gcc do fancy arithmetic, and still can't get it to fail:
|
Interesting that the difference is a factor of 2. Makes me suspicious of the handling of the exponent in the floating point.
|
Tried Arduino float arithmetic on 32u4 and M0. |
I'll take a look at the code for MP/CP tomorrow. Looks like a bug to me. |
Hmm. |
@ladyada Do you see the same behavior on master? It looks as if this change upstream may be related. |
@willingc The examples I gave above were run on master (2.0.0 past beta1). |
Thanks @dhalbert. If possible, would you mind running exactly the same example? Or did you run the exact same code, receive the same output, and not post it? |
@willingc This is the absolute latest master, with the v1.9.2 merge.
|
The bits used to represent CPy master, on atmel-samd and esp8266:
Python 3.5.2:
CircuitPython unix port is also Notice If you press the "-1" button on the webpage form above, you get the |
The answer to what is going on here is that MicroPython stores single-precision floats in 30 bits, not 32. The lowest two bits are used to flag the bits as a float value. When a 32-bit float is converted to 30 bits, it is truncated, not rounded. The 32-bit 0.1 has a 1 in the least significant bit and this goes to a 0 when truncated (and it would round down anyway). I tried extending the print precision to more decimal digits, but it still prints as "0.1", because that's the closest representation after rounding; "0.099999" is further from the actual value than "0.1" is. MicroPython only prints six digits of precision. Trying to print more digits gives peculiar results, like 1/3 printing as "0.333333325" . MicroPython even adjusted the number of digits of precision it printed to avoid oddities like this. We could have 32-bit to 30-bit conversion do rounding, but that might introduce other numerical issues, and might make porting code between MicroPython and CircuitPython weirder. And it wouldn't actually fix the 0.1 problem here, because it would round down. |
oooh ok. got it! |
but on desktop...
i know that floats are imprecise, but this seems unusual...
The text was updated successfully, but these errors were encountered: