Грех и Кос дают неожиданные результаты для известных углов

Я уверен, что это действительно глупый вопрос, но когда я передаю угол 180 градусов в функции cos () и sin () в c / c ++, я получаю неправильное значение. Я знаю, что это должно быть:
грех 0.0547 и cos 0.99
но я получаю грех 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;
}

Спасибо 🙂

-2

Решение

C / C ++ обеспечивает sin(a), cos(a), tan(a)и т. д. функции, для которых требуется параметр с радиан единицы, а не степени. double DegreesToRadians(d) выполняет преобразование, которое близко но приблизительные, так как результаты конвертации округлены. Также машина M_PI близко, но не то же значение, что и математическое иррациональное π,

Код ОП с 180 перешел к DegreesToRadians(d) а затем sin()/cos() дает результаты, которые отличаются от ожидаемых из-за округления, конечной точности double() и возможно слабое значение для PI,

Улучшение заключается в уменьшении аргументов в степени перед вызовом функции триггера. Ниже приведено уменьшение угла сначала до диапазона от -45 ° до 45 °, а затем sin(), Это обеспечит большие значения N в sind(90.0*N) --> -1.0, 0.0, 1.0, , Замечания: 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
...
9

Другие решения

Прежде всего, косинус 180 градусов должен быть равен -1Таким образом, результат, который вы получили, правильный.

Во-вторых, иногда не получается точный значения при использовании sin/cos/tan и т.д. функционирует как всегда результаты, наиболее близкие к правильным. В вашем случае значение, которое вы получили от sin ближайший к нулю.

Значение sin(PI) что у вас отличается от нуля только в девятую (!) цифра после плавающей запятой. 3.5897934739308216e-009 почти равно 0.000000004 и это почти равно нулю.

9

У меня та же проблема, что и при преобразовании приложения в 64-разрядную версию.
Мое решение заключается в использовании новых функций math.h __cospi () и __sinpi ().
Производительность аналогична (даже на 1% быстрее), чем cos () и sin ().

//    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);

Из математики:

/*  __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.                 */
5
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector