python - 为什么Python在除以sin()的结果时给出很大的错误

标签 python rounding-error

我试图找到我找到的方程中 n 的前 10 个整数输入的值:x = sin(2π/n)/sin(π/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),该线在一个点和相距 2 点的另一点之间延伸,呈 n 个等边为 1 且所有角都相等的形状(边长为 1) 的等边形的最小对角线。

最佳答案

对于第二个结果,从绝对值来看,影响相当小: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

how did the first result end up with -2.0, I might expect it to return something close to zero or an error / nan?

第一个结果是当 i 为 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 的两倍,因为当您将具有误差范围的值加倍时,误差会增加margin 也会加倍,并且不可能将 pi 表示为 float 而不出现任何错误。推测:该误差通过 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。

关于python - 为什么Python在除以sin()的结果时给出很大的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30341440/

相关文章:

python - Django 教程 1 错误

python - 为什么我的 scanf 捕捉到我从 Popen 发出的命令

python - jinja2 for ... if 循环中的第一个 x 项

c# - 无法通过c#代码将小数插入到sql server表中

Javascript 舍入失败

python - 使用 random.shuffle (Python) 从随机打乱列表中删除函数

python - 值错误 : y contains previously unseen labels: 'A' using OrdinalEncoder

rounding - 四舍五入标准-财务计算

java - Java数字,“人类”舍入

java - Java 6 和 Java 8 中不同的舍入结果