Str*_*667 3 floating-point precision rust
对于u64小于 2 ^ 54 的数字,可以通过强制转换为 来完成,而不会造成太大的精度损失f64:
((6 as f64) % 1.5) < f64::EPSILON
Run Code Online (Sandbox Code Playgroud)
对于较大的数字,将会有显着的精度损失:
1u64 << 63 // 9223372036854775808
(1u64 << 63) as f64 // 9223372036854776000
Run Code Online (Sandbox Code Playgroud)
并且将检查不同数字的可分性。
Context : JSONSchema 的multipleOf关键字实现
问题:检查不符合尾数大小(53)的u64/i64数字的可整性的最有效方法是什么?f64f64::MANTISSA_DIGITS
这是一个给定的解决方案,它u是某个整数并且x是一个有限的非零 IEEE-754 binary64 数,我们用它来进行 IEEE-754 算术。x假定代表一个特定数字,如 IEEE-754 所指定,并且x不考虑获取时发生的先前舍入误差。这个答案涉及所涉及的数学,而不是 Rust 语义,因为我不熟悉 Rust。
首先,找出x= F• 2的表示E,其中F是奇数,E是整数。一个简单的方法是:
F为x和E为 0。F不是整数,乘以F2 并从 中减去 1 E。F是偶数时,除以F2 并在 上加 1 E。以上所有操作都可以在 IEEE-754 算法中执行,没有舍入错误。如果 Rust 提供了一种分离浮点数的有效数和指数的方法,类似于 C 的frexp功能,那么将其合并到上面可以提高效率。
现在考虑是否u是x= F•2的倍数E。根据定义,当且仅当存在一个整数k使得u= k• F• 2 E。我们将看到这是这样的,当且仅当u是 2 的倍数F并且 是 2 的倍数E,并且这些中的每一个都可以被测试。
如果 2E是一个整数(E是非负数)并且这样的 ak存在,则u是 2 的倍数F并且是 2 的倍数E。相反,如果u不是 2 的倍数F或不是 2 的倍数E,则不k存在(通过算术基本定理)。
F必须在请求的整数格式的范围内(最多 53 位),我们假设F可以转换为该格式。然后可以测试uby 的整除性F。如果 2E超过u表示的整数格式的最大值,则u不是 2 的倍数E。否则,E可以将2转换为格式,并可以测试u被 2的整除性E。
如果 2E不是整数(E是负数),那么,如果所需的k存在(所以u是 的倍数F),它是 2 的倍数?E. 相反,如果k不是 2 的倍数?E,则k• F• 2E不是整数,因此不能等于u。因此u是x当且仅当u的倍数 是 的倍数F。