为什么相同的 32 位浮点数在 JavaScript 和 Rust 中不同?

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

在JavaScript中,38_579_240_960转换为32位浮点数时不变:

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

但是 in Rust,四舍五入为 38579240000。怎么样?

fn main() {
     println!("{}", 38_579_240_960_f32);` // 38579240000
}

虽然 38,579,240,960 可以准确表示为 IEEE-754 32 位浮点数,但尾部 960 并不重要。 24位的尾数只能表达约7个有意义的数字。上方和下方的下一个可表示值是 38,579,245,05638,579,236,864。因此,数字 38,579,240,960 是跨越数万的范围内最接近的可表示值。

因此,即使您将 1000 添加到该值,两种语言都不会更改其输出:

38579240960
38579240000

所以不同之处在于 JavaScript 打印出所表示的确切值,而 Rust 仅打印出最小数字以唯一地表达它。

如果您希望 Rust 输出看起来像 JavaScript 的,您可以像这样指定精度 (playground):

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

我不会把其中一个称为 rightwrong ,但是 Rust 的默认格式的一个优点是你不需要得到一种错误的精确感。

另请参阅:

  • How do I print a Rust floating-point number with all available precision?
  • Rust: Formatting a Float with a Minimum Number of Decimal Points

您的代码片段等同。 JS 打印 f64,而 Rust 打印 f32.

JavaScript 没有 32 位浮点类型。当您从 Float32Array 中读取一个元素时,它会隐式转换为 64 位 double,因为这是 JS 可以看到该值的唯一方式。

如果您在 Rust 中执行相同的操作,它会打印相同的值:

println!("{}", 38_579_240_960_f32 as f64);
// 38579240960