IEEE浮点错误能否让我错过素数搜索的一个因素?

时间:2013-10-16 19:10:17

标签: floating-point primes

在简单的素性检查中,通常的做法是检查从2到max = floor(sqrt(n))的除数。

在IEEE定义的浮点运算(比如32位和64位数)中,浮点错误是否会使未命中的因素略大于max

例如,max = floor(sqrt(REALLY_BIG_N)),但(max + 1) * something = REALLY_BIG_N


如果我的问题不完全清楚,请发表评论。

(请注意,我对这里的primality检查备选方案不感兴趣,或者通过使用sqrt来避免使用x * x < n - 我的问题实际上是关于它是否适用于IEEE浮点运算。)

3 个答案:

答案 0 :(得分:3)

没有

我认为max+1可以表示为浮点值(它不是很大,超出了浮点格式可以表示区间中所有整数的区间)。

我还假设something中的(max+1) * something是大于max的整数。否则,先前在寻找除数时会发现它(或更小的因子)。这意味着 n ≤( max +1)•( max +1)。

正确实现的sqrt返回最接近其参数平方根的可表示值。因此,如果n的数学平方根至少为x+1,则sqrt(n)必须返回x+1或更高;它无法返回x,因为x距离平方根比x+1更远。因此,max = floor(sqrt(n))的结果不小于floor的数学值(sqrt( n ))。

对于IEEE-754 64位二进制(以下称double),最多2 53 的所有整数都是可表示的。 2 53 +1是第一个不可表示的整数。因此,上面告诉我们sqrt(n)足以满足所有n,但不包括(2 53 +1) 2 。当然,许多大的整数在double中都不能完全表示,所以你不能将它们传递给sqrt

答案 1 :(得分:3)

补充Eric Postpischil的回答:是的,然后再没有。这取决于floor(sqrt(n))非常大的情况下我们将如何解释n

正如在Eric的回答中,让我们假设IEEE 754二进制64格式浮点和正确舍入sqrt,通常采用圆形连接到均匀舍入模式。我还假设访问n的任意精度整数类型。

第一种解释:假设允许n采用任何整数值,floor(sqrt(n))将被解释为floor(sqrt(convert_to_double(n)))。然后,n >= 2^1024 - 2^970会立即出现问题,因为此时convert_to_double会溢出。 (我假设convert_to_double也是正确的四舍五入。)从另一端开始,Eric的答案已经表明我们很擅长但不包括n = (2^53 + 1)^2,正如他所说,{{ 1}}是一个问题案例:n = (2^53 + 1)^2的值为convert_to_double(n),一个小于真值,2^106 + 2^54将向下舍入为sqrt(convert_to_double(n)),这意味着您的试用版除法函数将错过因子2^53。但是,考虑到2^53 + 1可以被2^53 + 13整除,试验部门很可能已经发现了其他因素,因此缺少107可能不是问题。在这种情况下,2^53+1应被视为第一个问题案例。 (n = (2^53 + 5)^2是素数。)

第二种解释:假设2^53 + 5被约束为一个正整数,它可以完全表示为double。然后一个简洁的事实是n的任何除数也必须完全可以表示为双精度:n可以用n形式写成一些非负指数m•2^e和奇数e的整数mm < 2^53的任何除数都可以n的形式写成d•2^f d的{​​{1}}和exponent { {1}} m。但是现在如果f0 <= f <= e的除数小于x的精确平方根,n可以完全表示为double,那么 nearest < / em> n的平方根的可表示的double必须大于或等于x。因此,最高n的试验分区例程不能错过x

只是为了好玩:在这里,我们只担心floor(sqrt(n))的值x给出的值太小。n如果您对floor(sqrt(n))给出的值太大的情况感兴趣,那么第一个示例会在floor(sqrt(n))之前发生很多。 (证明作为练习留下。)

当然,这完全是学术性的:如果您正在进行数字大于n = (2^26 + 1)^2 - 1的试验分组,那么您将等待时间来获得任何结果。 ..

答案 2 :(得分:1)

在处理素数时没有理由使用浮点运算。永远!您应该循环直到max,其中d * d > n是试验除数,而d是正在测试的数字,而不是计算n。如果必须计算平方根,编写自己的函数,只使用整数运算;牛顿的方法与整数完美匹配。

编辑:这是一个计算整数平方根的简单函数:给定一个整数nisqrt(n)返回*x不超过的最大整数x * x n;所有除法都是整数除法,它会截断任何小数余数:

function isqrt(n)
    x := n
    y := (x + n // x) // 2
    while y < x
        x := y
        y := (x + n // x) // 2
    return x