Python中使用多边形计算圆周率时如何避免大浮点数自动舍入
问题根源
你碰到的问题本质是Python默认浮点数精度上限导致的:
- 标准
float类型是双精度浮点数,仅能保留约15~17位有效数字,超过这个范围的数值本身就不会被正确存储,你用.100f输出的后面位数都是浮点数编码自带的无效冗余值,自然不会随着边数调整变化 math库的所有三角函数、弧度转换函数返回值都是float类型,天生带精度限制,再怎么调整输出格式也拿不到更高精度的结果
解决方法
改用Python内置的decimal模块做高精度计算,这个模块支持自定义精度,还自带了高精度的三角函数、弧度转换实现,你可以根据需要的位数提前设置计算精度。
修改后的可运行代码
from decimal import Decimal, getcontext import math # 先设置计算精度,比如要算100位的话,设置成110位预留计算余量,避免中间运算损失精度 getcontext().prec = 110 # 高精度的pi真值,用来对比正确位数 PI_REFERENCE = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679" print("--------------------------------") n = int(input("Number of sides: ")) # 高精度计算alfa:180度转弧度再除以n alfa = Decimal(math.pi) / Decimal(n) # 计算上下界和近似值,用Decimal的tan和sin方法 big_pi = Decimal(n) * alfa.tan() small_pi = Decimal(n) * alfa.sin() approx_pi = (big_pi + small_pi) / Decimal(2) # 转成字符串对比正确位数 approx_str = format(approx_pi, 'f') counter = -1 max_check = min(len(approx_str), len(PI_REFERENCE)) for i in range(max_check): if approx_str[i] == PI_REFERENCE[i]: counter += 1 else: break # 输出结果 print("--------------------------------") print(f"{small_pi} < pi < {big_pi}") print("--------------------------------") print(f"Average of both values: {approx_pi}") print("--------------------------------") print(f"first {counter} digits correct")
额外说明
你可以根据自己需要计算的位数调整getcontext().prec的值,一般比目标位数多10~20位即可,预留中间运算的精度损失空间;边数n越大,能拿到的正确位数越多,当n足够大时,正确位数会趋近于你设置的prec值。
内容的提问来源于stack exchange,提问作者M.DeBaecke
相关产品推荐
相关产品推荐

