为什么在分割sin()的结果时python会给出较大的错误 - python

我试图为我发现的方程式x = sin(2π / n) / sin(π / n)查找n的前十个整数输入的值。我写的找到它们的代码得到的输出令人惊讶:

>>> for i in range(1, 11):
        print math.sin(2 * math.pi / i) / math.sin(math.pi / i)

-2.0
1.22464679915e-16
1.0
1.41421356237
1.61803398875
1.73205080757
1.8019377358
1.84775906502
1.87938524157
1.90211303259

我意识到会有舍入错误,因此以下结果完全不会令我惊讶:

>>> math.sin(2 * math.pi)
-2.4492935982947064e-16
>>> math.sin(math.pi)
1.2246467991473532e-16

问题是,第一个结果如何以-2.0结尾,我可能期望它返回接近零或错误/ nan的值?

如果您有兴趣知道,此方程式应给出一条线的长度(x),该线的长度在一个点与另一个点之间延伸,两个点之间的距离等于n个边等于1且所有角度相等的形状(最小对角线的长度)边长为1的等值线的长度。

python大神给出的解决方案

对于第二个结果,绝对影响是很小的:1.22464679915e-16是一个很小的数字,非常接近零,大约为0.00000000000000012246

如果您只是想避免对您的结果显示方式产生重大影响的小错误,请使用格式字符串,例如:

for i in range(1, 11):
    print "{0:.10f}".format(math.sin(2 * math.pi / i) / math.sin(math.pi / i))

输出:

-2.0000000000
0.0000000000
1.0000000000
1.4142135624
1.6180339887
1.7320508076
1.8019377358
1.8477590650
1.8793852416
1.9021130326

第一个结果如何以-2.0结束,我可能期望它返回接近零或错误/ nan的值?

第一个结果是当我为1时,因此简化为:

math.sin(2 * math.pi) / math.sin(math.pi)

由于浮点错误,math.sin(2 * math.pi)评估为-2.44921270764e-16,而math.sin(math.pi)评估为1.22460635382e-16

-2.44921270764e-16 / 1.22460635382e-16的浮点除法得到-2.0,所以这是最终输出。

在没有浮点错误的情况下,math.sin(2 * math.pi)math.sin(math.pi)都应评估为零,但正是由于浮点实现和Python sin函数实现的结合导致了第一个浮点错误是秒的两倍,并且是负数,因此将它们相除得到-2。

math.pi * 2的内部表示形式中的浮点错误是math.pi的两倍,因为当您使用错误裕量对值进行加倍时,错误裕量也会加倍,并且如果不使用pi则无法将pi表示为浮点数错误。推测:该误差在sin计算中传播,并且由于在sin计算中涉及到与pi到2 pi范围内的sin函数是0到pi范围内的函数的负数这一事实有关而引入了负数。

如果要将极小的值四舍五入,可以使用numpy.around舍入到给定的小数位数,例如:

import numpy
for i in range(1, 11):
    print numpy.around(numpy.sin(2 * numpy.pi / i), 15) / numpy.around(numpy.sin(numpy.pi / i), 15)

这将为第一个结果产生一个nan。