我目前正在开发一个项目,将 js 代码移植到 Rust。在某些边缘情况下,两个浮点数相加在一起并丢失一定位精度时,会反复出现问题。
当 JavaScript 中精度丢失时,浮点数会被截断。然而,在生锈情况下,浮子是圆形的。 f64 是否有某种方法或实现可以修改此行为?我本质上需要 Rust 代码来完美模仿 js 代码。
示例:
-19.04345703125 + -7.9822540283203125 = -27.025711059570313 //rust
-19.04345703125 + -7.9822540283203125 = -27.025711059570312 //javascript
JavaScript 和 Rust 都遵循浮点数的 IEEE-754 标准,并且底层二进制值不会丢失精度:
let float: f64 = -19.04345703125 + -7.9822540283203125;
let int = float.to_bits();
println!("{int}"); // 13851672315927986176
var buf = new ArrayBuffer(8);
(new Float64Array(buf))[0] = -19.04345703125 + -7.9822540283203125;
console.log((new BigUint64Array(buf))[0]); // 13851672315927986176n
该二进制值对应于十进制
-27.0257110595703125
。
将浮点数格式化为字符串时,会使用不同的默认值。但是,您可以通过指定要截断的精确小数位数来覆盖默认值:
let float: f64 = -19.04345703125 + -7.9822540283203125;
println!("{float:.15}"); // -27.025711059570312
// '-27.025711059570312'
Intl.NumberFormat('en-US',{ minimumFractionDigits: 15, maximumFractionDigits: 15 }).format(-19.04345703125 + -7.9822540283203125)