Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are the same 32-bit floats different in JavaScript and Rust?

In JavaScript, 38_579_240_960 doesn't change when converted to a 32-bit float:

console.log(new Float32Array([38_579_240_960])[0]); // 38579240960

But in Rust, it gets rounded to 38579240000. Howcome?

fn main() {
     println!("{}", 38_579_240_960_f32);` // 38579240000
}
like image 346
GirkovArpa Avatar asked Dec 13 '22 07:12

GirkovArpa


2 Answers

While 38,579,240,960 is able to be represented as an IEEE-754 32-bit floating point number exactly, the trailing 960 is not significant. The 24-bit mantissa can only express about 7 meaningful digits. The next representable values above and below are 38,579,245,056 and 38,579,236,864. So the number 38,579,240,960 is the closest representable value in a range spanning in the tens-of-thousands.

So even if you add 1000 to the value, neither languages change their output:

38579240960
38579240000

So the difference is that JavaScript is printing out the exact value that is represented while Rust is only printing out the minimum digits to uniquely express it.

If you want the Rust output to look like JavaScript's, you can specify the precision like so (playground):

println!("{:.0}", 38579240960f32); // display all digits up until the decimal
38579240960

I wouldn't call either one right or wrong necessarily, however one advantage of Rust's default formatting is that you don't get a false sense of precision.

See also:

  • How do I print a Rust floating-point number with all available precision?
  • Rust: Formatting a Float with a Minimum Number of Decimal Points
like image 90
kmdreko Avatar answered Dec 22 '22 00:12

kmdreko


Your code snippets are not equivalent. JS prints f64, and Rust prints f32.

JavaScript does not have a 32-bit float type. When you read an element out of Float32Array it is implicitly converted to 64-bit double, because this is the only way JS can see the value.

If you do the same in Rust, it prints the same value:

println!("{}", 38_579_240_960_f32 as f64);
// 38579240960
like image 20
Kornel Avatar answered Dec 21 '22 22:12

Kornel