当使用特定值计算两个 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 {
编译器现在确定 u
和 v
的值属于 f32
类型。
那么您正在使用 .dot()
方法,它可以处理 f32
和 f64
。 u
和v
的类型已经定义为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/