Rust 如何在精度损失最小的情况下检查大于2^54的u64数是否可以被f64整除?
对于小于2^54的Rust 如何在精度损失最小的情况下检查大于2^54的u64数是否可以被f64整除?,rust,floating-point,precision,Rust,Floating Point,Precision,对于小于2^54的u64编号,可以通过铸造到f64,而不会造成太多精度损失: ((6为f64)%1.5)考虑 u>代码>是代码> x = f>代码>的倍数。2代码代码>。根据定义,当且仅当存在整数k时,u=k•F•2E。当且仅当u是F的倍数,并且是2E的倍数时,我们才会看到这一点,并且每个都可以测试 如果2E是整数(E是非负的),并且存在这样的k,那么u是F的倍数,是2E的倍数。相反,如果u不是F的倍数或不是2E的倍数,则不存在这样的k(通过算术基本定理) F必须在请求的整数格式的范围内(最多
u64
编号,可以通过铸造到f64
,而不会造成太多精度损失:
((6为f64)%1.5)
对于较大的数字,将有显著的精度损失:
1u64这里有一个解决方案,假设u
是一个整数,x
是一个有限的非零IEEE-754二进制64数,我们使用它进行IEEE-754算术<根据IEEE-754的规定,假定code>x
代表一个特定数字,并且不考虑在获取x
时出现的先前舍入误差。这个答案涉及到相关的数学,而不是锈的语义,因为我不熟悉锈
首先,找到x
=F
•2E
的表示形式,其中F
是奇数整数,E
是整数。一个简单的方法是:
- 将
设置为F
并将x
设置为0E
- 当
不是整数时,将F
乘以2,然后从F
中减去1E
- 当
为偶数时,将F
除以2,然后将1添加到F
E
frexp
函数,那么将其合并到上述函数中可以提高效率
>考虑<代码> u>代码>是代码> x = <代码> f>代码>的倍数。2代码<代码>代码>。根据定义,当且仅当存在整数
k
时,u
=k
•F
•2E
。当且仅当u
是F
的倍数,并且是2E
的倍数时,我们才会看到这一点,并且每个都可以测试
如果2E
是整数(E
是非负的),并且存在这样的k
,那么u
是F
的倍数,是2E
的倍数。相反,如果u
不是F
的倍数或不是2E
的倍数,则不存在这样的k
(通过算术基本定理)
F
必须在请求的整数格式的范围内(最多53位),我们假设F
可以转换为该格式。然后可以测试u
被F
整除。如果2E
超过表示u
的整数格式的最大值,则u
不是2E
的倍数。否则,可以将2E
转换为格式,并且可以测试u
被2E
整除的情况
如果2
E
不是整数(E
为负),那么,如果所需的k
存在(因此u
是F
的倍数),则它是2的倍数−<代码>E。相反,如果k
不是2的倍数−E
,则k
•F
•2E
不是整数,因此它不能等于u
。因此,u
是x的倍数
当且仅当u
是F的倍数
这个问题表明你将f64
视为无限精确,对吗?哦,我会纠正这个问题,我的意思是-以最小的精度损失这首先是一件值得怀疑的事情。我不认为您的示例实现可以精确表示整数的情况是您想要的。即使您尽可能精确地表示可表示为f64的整数a和b的商,由于各种原因,a%q
可能比浮点类型的ε大得多。即使在这种情况下也很难做到这一点。因此,在任何情况下,舍入和限制到u64
和f64
都是不符合要求的。您需要将序列化JSON中的所有数字视为精确的,并对它们执行任意精度算术,而不进行任何舍入或ε。您选择的用于演示精度损失的特定示例实际上并不涉及任何值的更改<代码>(1u64