[英]Comparison of two floats in Rust to arbitrary level of precision
How can I do a comparison at an arbitrary level of precision such that I can see that two numbers are the same?如何在任意精度级别进行比较,以便我可以看到两个数字相同? In Python, I would use a function like round()
, so I am looking for something equivalent in Rust.在 Python 中,我会使用像round()
这样的函数,所以我在 Rust 中寻找等价的东西。
For example I have:例如我有:
let x = 1.45555454;
let y = 1.45556766;
In my case, they are similar up to 2 decimal places.在我的情况下,它们相似到小数点后 2 位。 So x
and y
would become 1.46 for the purposes of comparison.因此,为了比较, x
和y
将变为 1.46。 I could format these, but that surely is slow, what is the best Rust method to check equivalence, so:我可以格式化这些,但这肯定很慢,检查等效性的最佳 Rust 方法是什么,所以:
if x == y { // called when we match to 2 decimal places}
To further elucidate the problem and give some context.进一步阐明问题并提供一些背景信息。 This is really for dollars and cents accuracy.这真的是为了美元和美分的准确性。 So normally in python
would use the round()
function with all its problems.所以通常在python
会使用round()
函数来解决所有问题。 Yes I am aware of the limitations of floating point representations.是的,我知道浮点表示的局限性。 There are two functions that compute amounts, I compute in dollars and need to handle the cents part to the nearest penny.有两个计算金额的函数,我以美元计算,需要将美分部分处理到最接近的一分钱。
The reason to ask the community is that I suspect that if I roll my own, it could hit performance and it's this aspect - which is I why I'm employing Rust, so here I am.询问社区的原因是我怀疑如果我自己动手,它可能会影响性能,这就是我使用 Rust 的原因,所以我在这里。 Plus I saw something called round() in the Rust documentation, but it seems to take zero parameters unlike pythons version.另外,我在 Rust 文档中看到了一种叫做round() 的东西,但与 python 版本不同,它似乎采用零参数。
From the Python documentation:来自 Python 文档:
Note The behavior of
round()
for floats can be surprising: for example,round(2.675, 2)
gives2.67
instead of the expected2.68
.注意round()
对浮点数的行为可能令人惊讶:例如,round(2.675, 2)
给出2.67
而不是预期的2.68
。 This is not a bug: it's a result of the fact that most decimal fractions can't be represented exactly as a float.这不是错误:这是大多数十进制分数不能完全表示为浮点数的结果。
For more information, check out What Every Programmer Should Know About Floating-Point Arithmetic .有关更多信息,请查看每个程序员应该了解的关于浮点运算的知识。
If you don't understand how computers treat floating points, don't use this code .如果您不了解计算机如何处理浮点数,请不要使用此代码。 If you know what trouble you are getting yourself into:如果您知道自己遇到了什么麻烦:
fn approx_equal(a: f64, b: f64, decimal_places: u8) -> bool {
let factor = 10.0f64.powi(decimal_places as i32);
let a = (a * factor).trunc();
let b = (b * factor).trunc();
a == b
}
fn main() {
assert!( approx_equal(1.234, 1.235, 1));
assert!( approx_equal(1.234, 1.235, 2));
assert!(!approx_equal(1.234, 1.235, 3));
}
A non-exhaustive list of things that are known (or likely) to be broken with this code:已知(或可能)被此代码破坏的事物的非详尽列表:
approx_equal(0.09, -0.09, 1)
)接近于零的值 ( approx_equal(0.09, -0.09, 1)
)A potential alternative is to use either a fixed-point or arbitrary-precision type, either of which are going to be slower but more logically consistent to the majority of humans.一个潜在的替代方法是使用定点或任意精度类型,这两种类型都会变慢,但对大多数人来说在逻辑上更一致。
This one seems to work pretty well for me.这个对我来说似乎很有效。
fn approx_equal (a:f64,b:f64,dp:u8) -> bool {
let p:f64 = 10f64.powf(-(dp as f64));
if (a-b).abs() < p {
return true;
} else {
return false;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.