这是我不期待的。我知道这些数字并非100%准确,但我并不期望互补角度给出sin
和cos
的不同结果:
以下函数返回0.70710678118654746000000...
sin(45 * PI / 180.0);
这个follwing函数返回0.70710678118654757000000...
cos(45 * PI / 180.0);
所以,它是:
0.707106781186547**46**000000... vs
0.707106781186547**57**000000...
并且不仅那些...... sin(1 * PI / 180.0)
也会返回与cos(89 * PI / 180.0)
略有不同的数字,尽管它们应该相同。
此外,它不仅是sin
与cos
问题,而且还是sin
与sin
问题:sin(1 * PI / 180.0)
返回与sin(179 * PI / 180.0)
不同的值,它们应该是相同的。
我尝试使用弧度而不是度数,并且存在完全相同的差异,我尝试使用小的PI值,一个巨大的PI值(大约100个小数以上),它们仍然不同,我尝试使用cmath
代替math.h
,我尝试使用M_PI
而不是我自己定义的PI
。
差异总是相同的,大约是第16个小数。不要误解我的意思,我知道我永远不会得到这些数字的100%精确值,但至少我期望得到相同的"不精确的"互补角度的sin
和cos
的值。这一切到底是怎么回事?
我需要它们是相同的,因为我正在处理的程序(我被要求做的重力模拟器)使用具有double
(我也试过float
)变量的对象这基本上是角度(度数或弧度,我已尝试过两者)。这些是物体用来移动的方向,我也需要角度来计算物体之间的相互作用。
角度在程序的每次迭代中都会发生变化,并且在每次迭代中,角度都会根据前一次迭代角度的计算而变化,因此如果在任何点上存在任何最小错误的角度值,那么该错误在每次迭代中越来越多地被放大。
该程序运行数千甚至数百万次迭代,因此价值的误差非常大!说清楚,行星最终摆脱了平衡,一切都变成了灾难,我真的很生气:(
P.S。我在Windows 7上,32位。
答案 0 :(得分:3)
我知道我永远不会得到这些数字的100%精确值,但AT 至少我期待获得与罪和cos相同的“不确定”价值 互补角度。
为什么呢?计算方式不同,因此会出现(并累积)不同的浮点错误。你看到的不是错误; FP算法不能通过数学定律预测。
顺便说一句,提供例如。 PI的30或100位数不会有任何不同 如果您的类型首先不能容纳30位数字。答案 1 :(得分:2)
无论计算方式如何,都应该返回相同的值
您的期望不正确。在IEEE-754中,只需要对基本运算符(+-*/
)和sqrt
进行正确舍入。像sin
,cos
,exp
这样的Trancendental函数不是必需的,因为它非常复杂
没有标准要求忠实地舍入超越功能。 IEEE-754(2008)建议,但不要求这些功能正确舍入。
现在,如果你看看你的价值观
↓
0.70710678118654746 = 0x1.6a09e667f3bccp-1
0.70710678118654757 = 0x1.6a09e667f3bcdp-1
↑
因此它们彼此相距1 p并且精确到双精度
不要误会我的意思,我知道我永远不会得到这些数字的100%精确值,但至少我期待得到相同的"不准确" sin的值和互补角的cos
不仅要计算sin
和cos
的单一算法。对于某些输入,每个输入都是正确的,但对于其他输入则不正确。它们也有不同的内存和时间要求,因此有些可能非常快,错误率更高,有些则需要更多的时间和内存,但它们可以实现更高的精度。
编译器实现可能会对这些函数使用不同的算法,因此如果您需要一致的结果,请在跨平台使用一个精心设计的库。例如,无论平台如何,GCC都使用MPFR来实现正确的舍入结果
GCC中端已与MPFR库集成。这允许GCC在编译时对内置数学函数的调用进行求值和替换,这些函数具有常数参数及其数学上等效的结果。在使用MPFR时,无论数学库实现或主机平台的浮点精度如何,GCC都可以生成正确的结果。这也允许GCC生成相同的结果,无论是否将本机编译或交叉编译配置编译到特定目标