c ++ Sin和Cos
我确信这是一个非常愚蠢的问题,但是当我将180度的angular度传递给c / c ++的cos()和sin()函数时,我似乎收到了一个不正确的值。 我知道它应该是:0.0547的罪和0.99的cos,但我得到3.5897934739308216e-009的罪和cos为-1.00000
我的代码是:
double radians = DegreesToRadians( angle ); double cosValue = cos( radians ); double sinValue = sin( radians );
DegreesToRadians()是:
double DegreesToRadians( double degrees ) { return degrees * PI / 180; }
谢谢 :)
C / C ++提供了sin(a)
, cos(a)
, tan(a)
等函数,它们需要一个带有弧度单位而不是度数的参数。 double DegreesToRadians(d)
执行转换是接近,但近似的转换结果四舍五入。 机器的M_PI
也接近,但与math上的无理数π
不一样。
OP的180
代码传递给DegreesToRadians(d)
,然后是sin()/cos()
,由于舍入, double()
有限精度以及PI
可能的弱值而给出的结果与预期不同。
一个改进是在调用trig函数之前以度为单位进行参数减less。 下面将angular度首先减小到-45°到45°的范围,然后调用sin()
。 这将确保在信号sind(90.0*N) --> -1.0, 0.0, 1.0
较大的N
值。 。 注意: sind(360.0*N +/- 30.0)
可能不完全等于+/-0.5
。 一些额外的考虑需要。
#include <math.h> #include <stdio.h> static double d2r(double d) { return (d / 180.0) * ((double) M_PI); } double sind(double x) { if (!isfinite(x)) { return sin(x); } if (x < 0.0) { return -sind(-x); } int quo; double x90 = remquo(fabs(x), 90.0, &quo); switch (quo % 4) { case 0: // Use * 1.0 to avoid -0.0 return sin(d2r(x90)* 1.0); case 1: return cos(d2r(x90)); case 2: return sin(d2r(-x90) * 1.0); case 3: return -cos(d2r(x90)); } return 0.0; } int main(void) { int i; for (i = -360; i <= 360; i += 15) { printf("sin() of %.1f degrees is % .*e\n", 1.0 * i, DBL_DECIMAL_DIG - 1, sin(d2r(i))); printf("sind() of %.1f degrees is % .*e\n", 1.0 * i, DBL_DECIMAL_DIG - 1, sind(i)); } return 0; }
产量
sin() of -360.0 degrees is 2.4492935982947064e-16 sind() of -360.0 degrees is -0.0000000000000000e+00 // Exact sin() of -345.0 degrees is 2.5881904510252068e-01 // 76-68 = 8 away // 2.5881904510252076e-01 sind() of -345.0 degrees is 2.5881904510252074e-01 // 76-74 = 2 away sin() of -330.0 degrees is 5.0000000000000044e-01 // 44 away // 0.5 5.0000000000000000e-01 sind() of -330.0 degrees is 4.9999999999999994e-01 // 6 away sin() of -315.0 degrees is 7.0710678118654768e-01 // 68-52 = 16 away // square root 0.5 --> 7.0710678118654752e-01 sind() of -315.0 degrees is 7.0710678118654746e-01 // 52-46 = 6 away sin() of -300.0 degrees is 8.6602540378443860e-01 sind() of -300.0 degrees is 8.6602540378443871e-01 sin() of -285.0 degrees is 9.6592582628906842e-01 sind() of -285.0 degrees is 9.6592582628906831e-01 sin() of -270.0 degrees is 1.0000000000000000e+00 // Exact sind() of -270.0 degrees is 1.0000000000000000e+00 // Exact ...
首先,180度的余弦应该等于-1
,所以你得到的结果是正确的。
其次,在使用sin/cos/tan
等函数时,有时不能得到确切的值,因为您总是得到最接近正确值的结果 。 在你的情况下,你从sin
获得的价值是最接近于零的。
您得到的sin(PI)
值仅在浮点数后的第9个 (!)数字中与零不同。 3.5897934739308216e-009
几乎等于0.000000004
,这几乎等于零。
将应用程序转换为64位时,我遇到与OP相同的问题。
我的解决scheme是使用新的math.h函数__cospi()和__sinpi()。
性能与cos()和sin()相似(甚至快1%)。
// cos(M_PI * -90.0 / 180.0) returns 0.00000000000000006123233995736766 //__cospi( -90.0 / 180.0) returns 0.0, as it should // #define degree2rad 3.14159265359/180 // #define degree2rad M_PI/ 180.0 // double rot = -degree2rad * ang; // double sn = sin(rot); // double cs = cos(rot); double rot = -ang / 180.0; double sn = __sinpi(rot); double cs = __cospi(rot);
从math.h:
/* __sinpi(x) returns the sine of pi times x; __cospi(x) and __tanpi(x) return the cosine and tangent, respectively. These functions can produce a more accurate answer than expressions of the form sin(M_PI * x) because they avoid any loss of precision that results from rounding the result of the multiplication M_PI * x. They may also be significantly more efficient in some cases because the argument reduction for these functions is easier to compute. Consult the man pages for edge case details. */