只是为了好玩,而且这个任务非常简单,我写了一个短小的程序来生成嫁接数,但由于浮点精度问题,它无法找到一些较大的例子。
这段代码缺少至少一个已知的嫁接数。9999999998 => 99999.99998999999999949999999994999999999374999999912... 在乘以10**5后似乎丢失了额外的精度。
所以我写了一个简短的C++程序来查看是不是我的CPU截断了浮点数,还是Python出了什么问题。
看起来我正在遇到浮点精度的限制,CPU正在截断剩余的位数,因为它认为剩余的差异是浮点误差。在Python下有没有解决这个问题的方法?还是我需要转向C语言并使用GMP或其他工具?
def isGrafting(a):
for i in xrange(1, int(ceil(log10(a))) + 2):
if a == floor((sqrt(a) * 10**(i-1)) % 10**int(ceil(log10(a)))):
return 1
a = 0
while(1):
if (isGrafting(a)):
print "%d %.15f" % (a, sqrt(a))
a += 1
这段代码缺少至少一个已知的嫁接数。9999999998 => 99999.99998999999999949999999994999999999374999999912... 在乘以10**5后似乎丢失了额外的精度。
>>> a = 9999999998
>>> sqrt(a)
99999.99999
>>> a == floor((sqrt(a) * 10**(5)) % 10**int(ceil(log10(a))))
False
>>> floor((sqrt(a) * 10**(5)) % 10**int(ceil(log10(a))))
9999999999.0
>>> print "%.15f" % sqrt(a)
99999.999989999996615
>>> print "%.15f" % (sqrt(a) * 10**5)
9999999999.000000000000000
所以我写了一个简短的C++程序来查看是不是我的CPU截断了浮点数,还是Python出了什么问题。
#include <cstdio>
#include <cmath>
#include <stdint.h>
int main()
{
uint64_t a = 9999999998;
printf("%ld %.15f %.15f %.15f %.15f\n", a, sqrt((double)a), sqrt((double)a)*1e4, sqrt((double)a)*1e5, sqrt((double)a)*1e6);
a = 999999999998;
printf("%ld %.15f %.15f %.15f %.15f\n", a, sqrt((double)a), sqrt((double)a)*1e5, sqrt((double)a)*1e6, sqrt((double)a)*1e7);
a = 99999999999998;
printf("%ld %.15f %.15f %.15f %.15f\n", a, sqrt((double)a), sqrt((double)a)*1e6, sqrt((double)a)*1e7, sqrt((double)a)*1e8);
return 0;
}
这将输出:
9999999998 99999.999989999996615 999999999.899999976158142 9999999999.000000000000000 99999999990.000000000000000
999999999998 999999.999998999992386 99999999999.899993896484375 999999999999.000000000000000 9999999999990.000000000000000
99999999999998 9999999.999999899417162 9999999999999.900390625000000 99999999999999.000000000000000 999999999999990.000000000000000
看起来我正在遇到浮点精度的限制,CPU正在截断剩余的位数,因为它认为剩余的差异是浮点误差。在Python下有没有解决这个问题的方法?还是我需要转向C语言并使用GMP或其他工具?