JavaScript和Rust函数之间返回值的偶尔差异

dm7nw8vv  于 2023-06-23  发布在  Java
关注(0)|答案(3)|浏览(146)

以下JavaScript函数始终按预期工作:

function getvalue(a, b, c) {
    Math.floor((a / b) % c)
}

当我在Rust中编写这个并通过wasm_bindgen在JS中使用它时,每隔一段时间,似乎随机地,我会得到一个与上面函数返回的值不同的结果:

pub fn get_value(a: f32, b: f32, c: f32) -> i32 {
    ((a / b) % c).floor() as i32
}

一些例子:

a = 33339077
b = 53.32715671989507
c = 3.5454545454545454

// JS -> 3, Rust -> 2

a = 33340860
b = 53.32715671989507
c = 3.5454545454545454

// JS -> 0, Rust -> 1

我在这里遗漏了什么,以及如何使Rust函数返回与JS函数相同的值?

czq61nw1

czq61nw11#

JavaScript使用双精度浮点数,但Rust函数使用单精度。如果你切换到f64,你会得到同样的结果:

pub fn get_value32 (a: f32, b: f32, c: f32) -> i32 {
    ((a / b) % c).floor() as i32
}

pub fn get_value64 (a: f64, b: f64, c: f64) -> i32 {
    ((a / b) % c).floor() as i32
}

fn main() {
    println!("f32: {}", get_value32 (33339077., 53.32715671989507, 3.5454545454545454));
    println!("f64: {}", get_value64 (33339077., 53.32715671989507, 3.5454545454545454));
}

给出:

f32: 2
f64: 3

Playground

tvz2xvvm

tvz2xvvm2#

f32的最大安全整数是16777215。大于此值的整数不能精确存储。看看这个rust代码:

fn main() {
    let a:f32 = 33339077.0f32;
    println!("{a:?}");
    // Output: 33339076.0
}

最接近33339077的值是33337076,所以a实际上是33339076,而不是33339077。
你可能注意到(33339076/b)%c2.98713,而(33339077/b)%c==3.0068869(即使使用更精确的算术)。当地板一个出来2和其他3。
要修复您的问题,请在整个代码中使用f64,而不是f32。请注意,在任何时候将a存储为f32都会引入不准确性,在调用函数之前转换为f64将为时已晚,数据已经丢失。

lrpiutwd

lrpiutwd3#

你的JS函数

function getvalue() {
    Math.floor((a / b) % c)
}

不定义abc。表达式(a/b) % c产生undefined。
但这并不重要,因为getvalue()并不返回值--默认情况下,它返回undefined。
您的Rust函数

pub fn get_value(a: f32, b: f32, c: f32) -> i32 {
    ((a / b) % c).floor() as i32
}

假设f32是单精度IEEE浮点数,i32是32位int。. . .好吧,它也不返回值。
但更多(和大多数?)重要的是,JS中的所有数值都是IEEE双精度浮点数。
参见Goldberg的论文“每个计算机科学家都应该知道的浮点运算”
https://pages.cs.wisc.edu/~david/courses/cs552/S12/handouts/goldberg-floating-point.pdf
https://www.itu.dk/~sestoft/bachelor/IEEE754_article.pdf
https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
参见What Every Programmer Should Know About Floating-Point Arithmetic,or, Why don’t my numbers add up?

相关问题