关于继续分数的Python代码
我正在试着理解下面这段Python代码在做什么。我先计算2的平方根,然后把它的小数部分除以1。这样做了5次,结果一直是一样的,但第6次和第7次的时候结果却变了。
为什么在第6次的时候,输出会变化,而输入值和前5次计算的是一样的呢?
import math as M
frct = M.sqrt(2)
# 1
frct = 1 / (frct - int(frct))
print frct # 2.41421356237
# 2
frct = 1 / (frct - int(frct))
print frct # 2.41421356237
# 3
frct = 1 / (frct - int(frct))
print frct # 2.41421356237
# 4
frct = 1 / (frct - int(frct))
print frct # 2.41421356237
# 5
frct = 1 / (frct - int(frct))
print frct # 2.41421356237
# 6
frct = 1 / (frct - int(frct))
print frct # 2.41421356238
# 7
frct = 1 / (frct - int(frct))
print frct # 2.41421356235
2 个回答
3
当你使用 print frct
时,它显示的 str(frct)
结果中的有效数字比实际需要的少,导致无法准确复现这个数字。如果把 print frct
改成 print repr(frct)
,你会发现前五次显示的数字并不相同,虽然它们变化得比较慢(开始的时候),所以它们的四舍五入结果保持一致:
2.4142135623730945
2.4142135623730985
2.414213562373075
2.414213562373212
2.4142135623724124
2.414213562377074
2.414213562349904
9
简单来说,Python在输出的时候会进行四舍五入 :)
import math as M
frct = M.sqrt(2)
for i in range(7):
frct = 1 / (frct - int(frct))
print 'Attempt %d: %.20f' % (i, frct)
详细一点说,浮点数并不是存储真实的值(没有双关的意思),而是存储一个指数和一个尾数。想了解更多,可以看看这个维基百科页面:http://en.wikipedia.org/wiki/Floating_point
基本上,浮点数是这样存储的:
Significant digits × base^exponent
如果你想在Python中得到更精确的结果,可以试试decimal模块:
import decimal
context = decimal.Context(prec=100)
frct = context.sqrt(decimal.Decimal(2))
print 'Original square root:', frct
for i in range(7):
frct = context.divide(1, frct - int(frct))
print 'Attempt %d: %s' % (i, frct)
输出结果:
Original square root: 1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573
Attempt 0: 2.414213562373095048801688724266222622763067167798368627068136427003657772608039155697953022512189319
Attempt 1: 2.414213562373095048801688723683379910288448158038030882339615025168647691299718507620657724911891709
Attempt 2: 2.414213562373095048801688727180436185136162216600057354932063779738350752352175486771948426117071942
Attempt 3: 2.414213562373095048801688706780941248524496874988236407630784335182989956231878308913506955872772859
Attempt 4: 2.414213562373095048801688825680854593346774866097140494471009059332623720827093783193465943198777227
Attempt 5: 2.414213562373095048801688132680869461024772261055702548455940065126184103929661474210576202848416747
Attempt 6: 2.414213562373095048801692171780866910134509900201052604731129303452089934643341550673727041448985316