为什么相同的32位浮点数在JavaScript和Rust中不同?
在 JavaScript 中,38_579_240_960转换为 32 位浮点数时不会改变:
console.log(new Float32Array([38_579_240_960])[0]); // 38579240960
回答
虽然38,579,240,960能够准确地表示为 IEEE-754 32 位浮点数,但尾随960并不重要。24 位尾数只能表示7有意义的数字。上下可表示的下一个值是38,579,245,056和38,579,236,864。因此,该数字38,579,240,960是数万个范围内最接近的可表示值。
因此,即使您添加1000到该值,两种语言都不会更改其输出:
38579240960
38579240960
38579240000
所以区别在于 JavaScript 打印出所表示的确切值,而 Rust 仅打印出最小数字来唯一地表达它。
如果你想让 Rust 的输出看起来像 JavaScript 的,你可以像这样指定精度(playground):
println!("{:.0}", 38579240960f32); // display all digits up until the decimal
我不一定会说对或错,但是 Rust 的默认格式的一个优点是您不会对精确度产生错误的感觉。
也可以看看:
- 如何以所有可用精度打印 Rust 浮点数?
- Rust:用最少的小数点格式化浮点数
- 这是 IEEE-754 浮点数的错误陈述。IEEE-754 标准很明确:每个浮点数据精确地代表一个数字或一个 NaN。“尾随 960”**是**重要的,它**用于算术,并且**确实**确定用它运算的结果。将浮点数视为近似值是错误的。他们是准确的。**运算**近似于实数运算;操作有效地将理想结果四舍五入到最接近的可表示数字……
回答
您的代码片段并不等效。JS 打印f64,Rust 打印f32.
JavaScript 没有 32 位浮点类型。当您Float32Array从中读取元素时,它会隐式转换为 64 位double,因为这是 JS 可以看到值的唯一方式。
如果你在 Rust 中做同样的事情,它会打印出相同的值:
println!("{}", 38_579_240_960_f32 as f64);
// 38579240960