C 浮点数学不精确

C 浮点数学不精确,c,floating-point,precision,C,Floating Point,Precision,我们知道cos(2mPI)=1,对于每一个整数m。 然而,我得到以下输出 value of m = 1.000000e+01 and value of cos(2*m*pi) = 1.000000000000000 value of m = 1.000000e+02 and value of cos(2*m*pi) = 1.000000000000000 value of m = 1.000000e+03 and value of cos(2*m*pi) = 1.000000000000000

我们知道cos(2mPI)=1,对于每一个整数m。 然而,我得到以下输出

value of m = 1.000000e+01 and value of cos(2*m*pi) = 1.000000000000000
value of m = 1.000000e+02 and value of cos(2*m*pi) = 1.000000000000000
value of m = 1.000000e+03 and value of cos(2*m*pi) = 1.000000000000000
value of m = 1.000000e+04 and value of cos(2*m*pi) = 1.000000000000000
value of m = 1.000000e+05 and value of cos(2*m*pi) = 1.000000000000000
value of m = 1.000000e+06 and value of cos(2*m*pi) = 1.000000000000000
value of m = 1.000000e+07 and value of cos(2*m*pi) = 1.000000000000000
value of m = 1.000000e+08 and value of cos(2*m*pi) = 0.999999999999997
value of m = 1.000000e+09 and value of cos(2*m*pi) = 0.999999999999998
value of m = 1.000000e+10 and value of cos(2*m*pi) = 0.999999999989970
value of m = 1.000000e+11 and value of cos(2*m*pi) = 0.999999999564035
value of m = 1.000000e+12 and value of cos(2*m*pi) = 0.999999854510183
value of m = 1.000000e+13 and value of cos(2*m*pi) = 0.999985451053279
value of m = 1.000000e+14 and value of cos(2*m*pi) = 0.999742535619873
value of m = 1.000000e+15 and value of cos(2*m*pi) = 0.888410566323832
value of m = 1.000000e+16 and value of cos(2*m*pi) = 0.718430574337184
value of m = 1.000000e+17 and value of cos(2*m*pi) = -0.438105159926831
value of m = 1.000000e+18 and value of cos(2*m*pi) = 0.176561618304251
value of m = 1.000000e+19 and value of cos(2*m*pi) = -0.114036978390490
value of m = 1.000000e+20 and value of cos(2*m*pi) = 0.689416156299807

为什么我们不总是计算正确的输出?当m值变大时,近似值会发生显著变化。不确定是哪种类型的浮点误差导致了这种情况。有什么帮助吗?

可能是因为PI本身的值(它的计算机表示,而不是数学值)不精确

它可能是
3.141592653589
(这是我脑海中所能记得的全部),但是,除非你有无限多的位来存储它(或者你使用符号而不是二进制编码形式),否则它永远不会完全准确

当你把它乘以更大的整数时,不精确性可能会增加

浮点表示法的变化无常是众所周知的,从IEEE754双精度表示法中只能获得大约15位精度。给出PI要求的关于。。。好。。。永无止境的比特数,一定要给点什么



我不完全确定什么样的应用程序会使用像
1020π
这样的值,我也不假装知道您的情况,但您可能需要考虑尝试将值钳制到一个更“合理”的范围,如
[0,2π)

,这可能是因为π本身的值(它的计算机表示,而不是数学值)不精确

它可能是
3.141592653589
(这是我脑海中所能记得的全部),但是,除非你有无限多的位来存储它(或者你使用符号而不是二进制编码形式),否则它永远不会完全准确

当你把它乘以更大的整数时,不精确性可能会增加

浮点表示法的变化无常是众所周知的,从IEEE754双精度表示法中只能得到大约15位精度。给定PI需要一个……嗯……永无止境的位数,必须给出一些东西



我不完全确定什么样的应用程序会使用像
1020π
这样的值,我也不假装知道您的情况,但您可能需要考虑尝试将值钳制到一个更“合理”的范围,如
[0,2π)

与PI最接近的64位浮点数(我称之为
piDouble
)与PI的精确值
piExact
之间的差值约为1.22E-16。差值
m*piExact-m*piDouble==m*(piExact-piDouble)
约为
m*1.22E-16

像余弦这样的函数是通过首先将角度减小到相对较小的角度范围来计算的,在该范围内,库与余弦有很好的近似


随着m变大,
m*1.22E-16首先变得足够重要,然后在角度缩减结果中占主导地位。

与PI最接近的64位浮点数(我称之为
piDouble
)和PI的精确值
piExact
)之间的差值约为1.22E-16。差值
m*piExact-m*piDouble==m*(piExact-piDouble)
是关于
m*1.22E-16

像余弦这样的函数是通过首先将角度减小到相对较小的角度范围来计算的,在该范围内,库与余弦有很好的近似


随着m变得越来越大,
m*1.22E-16
首先变得足够重要,然后在角度缩减结果中占主导地位。

欢迎使用浮点精度。您可能还想看看这里是如何计算余弦的。猜测一下,这可能是对排序的扩展,达到了一定的精度,并且参数值更大(
x
)将导致该扩展产生更大的不准确度。相关:@Olaf:YAW.
sin
cos
是所有实数的数学定义(事实上,也适用于所有复数)。但您所说的舍入误差是对的。@TonyK:Ok,我不确定“模数”是否-部分是否包含在定义中。感谢您纠正我。由于舍入错误是答案的一部分,我删除了我的评论。已经给出的答案解释了为什么会发生这种情况。如果您在实际场景中遇到这种情况,需要避免,请检查您的平台是否提供函数
cospi()
,其中
cospi(x)
计算cos(πx)。欢迎使用浮点精度。您可能还想在此处查看余弦的计算方法。猜测一下,这可能是排序扩展到某个精度和更大的参数值(
x
)将导致该扩展产生更大的不准确度。相关:@Olaf:YAW.
sin
cos
是所有实数的数学定义(事实上,也适用于所有复数)。但您所说的舍入误差是对的。@TonyK:Ok,我不确定“模数”是否-部分是否包含在定义中。感谢您纠正我。由于舍入错误是答案的一部分,我删除了我的评论。已经给出的答案解释了为什么会发生这种情况。如果您在实际场景中遇到这种情况,需要避免,请检查您的平台是否提供函数
cospi()
,其中
cospi(x)
计算cos(πx)。这只是我发现的教科书练习之一。我认为浮点溢出也会导致这种不精确性。当2*m*pi变得太大而无法在标准计算机系统中近似时。@rcgldr,小心点,我不确定(尽管我没有仔细检查)将
m/1.0
四舍五入到零可能在所有情况下都有效。这可能与整数数学
99/10
没有什么不同,整数数学将给出
9
,而不是“更正确的”
10
@paxdiablo-删除了我之前的评论。尽管fmod(m,1.0)对于m的任何整数值,应导致0.0,包括双精度中的任何m>=10^16