我认为 C 语言中 tan/atan 方法面临着数值精度问题。我想我在这里遗漏了一些东西,但我不知道是什么。
我附上了我所指的下面的代码,它尝试从一系列三角函数的数字( a
、 b
和 m6
)计算一些角度( m7
和 m8
)应用于这些角度(如代码注释所示),然后我反转这些角度来重建 m6
, m7
和m8
并将它们与原始数字进行比较,当我使用 double
时,我希望原始数字匹配到第 14 或第 15 位数字。数字。但是,正如您从输出中看到的那样,我无法解释 atan
存在一些数字差异。案例。有谁了解正在发生的事情吗?
a - atan() - -0.0003351970075579
a - atan2() - -0.0003351970075579
b - asin() - 0.0000856336001047
m6 - got [ -0.0000856336000000 ]
m6 - expected [ -0.0000856336000000 ]
m7 - got [ -0.0003351970000519 ]
m7 - expected [ -0.0003351970000000 ]
m8 - got [ 0.9999999401549271 ]
m8 - expected [ 0.9999999400000000 ]
您可以从键盘执行此链接中的代码:http://codepad.org/lzMMcgnb
#include <stdio.h>
#include <math.h>
int main()
{
/* m6 = -sin b*/
double m6 = -0.0000856336;
/* m7 = sin a * cos b */
double m7 = -0.0003351970000000;
/* m8 = cos a * cos b */
double m8 = 0.9999999400000000;
/* a = atan(m7 / m8) = atan2(m7,m8)*/
double a1 = atan(m7 / m8);
double a2 = atan2(m7 , m8);
double b = -asin(m6);
printf("a - atan() - %.16f\n", a1);
printf("a - atan2() - %.16f\n", a2);
printf("b - asin() - %.16f\n", b);
/* Inverse transformation */
double m6p = -sin(b);
double m7p = sin(a2) * cos(b);
double m8p = cos(a2) * cos(b);
printf("m6 - got [ %.16f ]\n", m6p);
printf("m6 - expected [ %.16f ]\n\n", m6);
printf("m7 - got [ %.16f ]\n", m7p);
printf("m7 - expected [ %.16f ]\n\n", m7);
printf("m8 - got [ %.16f ]\n", m8p);
printf("m8 - expected [ %.16f ]\n", m8);
return 1;
}
最佳答案
根据经验,作为标准 C 库实现提供的三角函数中从第 8 个有效位开始的任何错误都应被视为正常。 (根据我的经验,使用 sin
和 cos
实现比使用 tan
效果更好,这也适用于逆。)
C 标准和 IEEE754 浮点规范(C 中浮点采用的常见方案)都不要求这些函数与它们使用的数据类型一样精确(参见 sqrt
或IEEE754 要求返回最佳结果的算术运算符 +
、-
、*
和 /
) 。而且很多实现都注重执行速度而不是准确性。
如果您需要更高的精度,那么您需要将这些函数切换为保证更好结果的函数。
关于c - 使用 atan C 截断 double ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56628289/