-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Loss of precision in Integer -> Float autocast #11710
Comments
That could detect the error but what should the action taken be? Compilation error? |
Thanks @yxhuvud , I updated the issue. |
Yes, I think this should be a compilation error. If you don't care about integer precision, you wouldn't use an integer literal. We should also consider Float32 to Float64 autocasting. Float64's range is much bigger as well. Literals outside of Float32's range silently turn up as x : Float32
x = 1.7976931348623157e+308 # => Infinity Additionally, Float64 has higher precision than Float32. The problem with floating point literals is that they are almost always losing precision. 0.99999999_f32 # => 1.0
0.99999999_f64 # => 0.99999999
0.99999999999999999_f64 # => 1.0 So it's clear that a float literal is never really precise. Even that precise looking |
I realized the range problem isn't specific to autocasting, it also shows with regular literals: 1.7976931348623157e+308_f32 # => Infinity |
Integer-to-float autocasting can also produce infinities for def foo(x : Float32)
x
end
foo 1_u128 # => 1.0
foo 0xFFFFFF00_00000000_00000000_00000000_u128 # => 3.4028235e+38
foo 0xFFFFFF7F_FFFFFFFF_FFFFFFFF_FFFFFFFF_u128 # => 3.4028235e+38
foo 0xFFFFFF80_00000000_00000000_00000000_u128 # => Infinity
foo 0xFFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_u128 # => Infinity |
When adding number autocast for 1.3.0, one key aspect of the design was to preserve the precision of numbers. That's why it's possible to cast an Int32 to a Float64, but not to Float32. However, literal autocasting might lose precision:
Probably the easiest fix it to see if for FloatN the literal integer fits in an (U)Int(N/2) or, better still, check the mantissa of the type, and raise an appropriate compilation error message.
The text was updated successfully, but these errors were encountered: