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

Gir*_*rpa 4 javascript floating-point precision rust

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

console.log(new Float32Array([38_579_240_960])[0]); // 38579240960
Run Code Online (Sandbox Code Playgroud)

在 Rust 中,它被四舍五入为38579240000. 怎么来的?

fn main() {
     println!("{}", 38_579_240_960_f32);` // 38579240000
}
Run Code Online (Sandbox Code Playgroud)

kmd*_*eko 6

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

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

38579240960
Run Code Online (Sandbox Code Playgroud)
38579240000
Run Code Online (Sandbox Code Playgroud)

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

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

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

我不一定会说,但是 Rust 的默认格式的一个优点是您不会对精确度产生错误的感觉。

也可以看看:

  • 这是 IEEE-754 浮点数的错误陈述。IEEE-754 标准很明确:每个浮点数据精确地代表一个数字或一个 NaN。“尾随 960”**是**重要的,它**用于算术,并且**确实**确定用它运算的结果。将浮点数视为近似值是错误的。他们是准确的。**运算**近似于实数运算;操作有效地将理想结果四舍五入到最接近的可表示数字…… (4认同)

Kor*_*nel 5

您的代码片段并不等效。JS 打印f64,Rust 打印f32.

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

如果你在 Rust 中做同样的事情,它会打印出相同的值:

println!("{}", 38_579_240_960_f32 as f64);
// 38579240960
Run Code Online (Sandbox Code Playgroud)