Rust:f32 上奇怪的基于状态的舍入行为

标签 rust rounding-error

当使用特定值计算两个 nalgebra::Vector3 结构的点积时,我得到以下行为 ( link to playground ):

use nalgebra::{Point3, Vector3}; // 0.31.0

fn dot(v1: Vector3<f32>, v2: Vector3<f32>) -> f32 {
    v1.x * v2.x + v1.y * v2.y + v1.z * v2.z
    
}

fn main() {
    println!("Run 1:");
    let u = Vector3::new(1000., -1000., 0.);
    let v = Vector3::new(-0.69294637441651, 0.720989108085632, 0.);
    println!(
        "self-written dot-product: \t{:.32}",
        dot(u, v)
    );
    println!(
        "nalgebra dot-product: \t\t{:.32}",
        u.dot(&v)
    );
    println!("\nRun2:");
    let u = Vector3::new(1000., -1000., 0.);
    let v = Vector3::new(-0.69294637441651, 0.720989108085632, 0.);
    println!(
        "nalgebra dot-product: \t\t{:.32}",
        u.dot(&v)
    );
}

输出:

Run 1:
self-written dot-product:   -1413.93554687500000000000000000000000
nalgebra dot-product:       -1413.93554687500000000000000000000000
Run2:
nalgebra dot-product:       -1413.93548250214189465623348951339722

我必须能够依靠计算始终保持不变。有什么想法吗?

与我之前的问题相关,由于示例无效,我关闭了该问题 previous question

最佳答案

正如@aedm 在评论中提到的,您的dot() 函数是导致此行为的原因。作为一个初学者,我不太清楚它到底是什么原因,所以我在这里做了一个解释。

第一次定义变量时,

 9| println!("Run 1:");
10| let u = Vector3::new(1000., -1000., 0.);
11| let v = Vector3::new(-0.69294637441651, 0.720989108085632, 0.);

Rust 编译器不知道值的确切类型,它只知道它是float。如果没有额外信息,编译器将作为 default float type in Rust 落入 f64。 .

当您调用 dot(u, v) - 您让编译器知道确切的类型,因为您在函数声明中指定了它们:

 3| fn dot(v1: Vector3<f32>, v2: Vector3<f32>) -> f32 {

编译器现在确定 uv 的值属于 f32 类型。

那么您正在使用 .dot() 方法,它可以处理 f32f64uv的类型已经定义为f32,变量的类型不能改变,但是会导致.dot( ) 可以处理 f32,这让编译器很高兴。此时你得到:

Run 1:
-1413.93554687500000000000000000000000
-1413.93554687500000000000000000000000

之后,您将定义具有相同名称的新变量 - 同样,编译器没有关于变量类型的明确信息。但是这次没有 dot(u, v) 调用,只有 .dot() 而后者不需要 f32,所以编译器使用默认的 f64。最后你得到:

Run2:
-1413.93548250214189465623348951339722

关于Rust:f32 上奇怪的基于状态的舍入行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72774605/

相关文章:

rust - 使用 Rust 和 match 语句如何分配 TcpListener?

Matlab sin(pi) 及其与机器 epsilon 的关系

ios - 为 Collection View 舍入浮点值时出错

python - 什么时候使用浮点运算计算上限整数log2会失败?

rust - 过滤与迭代器中模式匹配的值的惯用方法

int - 如何获得 FFI 的机器大小的整数?

rust - 如何在 Rust 中将字符串中的所有字符大写?

rust - 是否有理由在 Substrate 中对特定类型使用通用特征?

php intval() 和 Floor() 返回值太低?

c++ - Qt:12.625 舍入 2 返回 12.62