-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
f64 Multiplication errors #90003
Comments
Same problem : #![allow(unused)]
fn main() {
let a: f64 = (-25252734735360000_f64 * 365_f64) + ( -25252734735360000_f64 * 0.2425_f64) ;
let b: f64 = -25252734735360000_f64 * 365.2425_f64;
println!("a = {}", a);
println!("b = {}", b);
assert_eq!(a, b);
} output: |
是rust f64 的运算跟go有很大的差异,我给rust提交了一个bug。rust-lang/rust#90003
These are IEEE floating-point errors unrelated to Rust. You would get the same error with any other language. |
I don't have this bug in golang. I think it is necessary to optimize rust in order to make it easier to use package main
import "fmt"
func main() {
var a int64 = -25252734735360000 * 365 - int64(25252734735360000 * 0.2425)
var b int64 = -25252734735360000 * 365.2425
fmt.Println(a==b)
} output: |
In Python 3 it's the same as in Rust: >>> a = -25252734735360000 * 365 - int(25252734735360000 * 0.2425)
>>> b = int(-25252734735360000 * 365.2425)
>>> a
-9223371966579724800
>>> b
-9223371966579725312 I think there's nothing to optimize in Rust here, nor to make it simpler to use. |
It seems that no programming languages agree on what in the correct result however it seems that most programming language produce the same result for the two expression. Godbolt |
This is because constants and number literals in Go have infinite precision[1] until you store them somewhere. If you instead store your numbers in variables and then refer to those in your multiplication, you will get the same results as Rust. [1]: SO |
I get the same mismatch in a C/C++ build: #include <iomanip>
#include <iostream>
#include <cassert>
using namespace std;
int main() {
double a = -25252734735360000.00 * 365.00 + (-25252734735360000.00 * 0.2425);
double b = -25252734735360000.00 * 365.2425;
cout << setprecision(32);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
assert(a == b);
return 0;
} prints
This looks to me like floating point arithmetic issues, not a rustc issue. |
This is the expected behavior. Numbers greater than 1 are not uniformly distributed when using doubles, and the distance between numbers that can be properly represented increases with larger numbers. The number 25252734735360000 is beyond the point where only even numbers can be represented, so some significant rounding errors should be expected. If you need arbitrary precision you should consider using a library for it, e.g. https://docs.rs/rug/0.6.0/rug/ |
Since this seems to be normal floating-point behaviour, I'm going to close this -- it doesn't seem like there's anything to change. |
I tried this code:
I expected to see this happen:
a == b , and the value is equal to -9223371966579724800
Instead, this happened:
a !=b
a = -9223371966579724800
b = -9223371966579725312
Meta
rustc --version --verbose
:Backtrace
The text was updated successfully, but these errors were encountered: