Усечение в числах двойной точности с atan C - PullRequest
2 голосов
/ 17 июня 2019

Я столкнулся с проблемой числовой точности в Си с методами tan / atan.Я предполагаю, что здесь что-то отсутствует, но я не знаю, что.

Я приложил нижеприведенный код, который пытается вычислить некоторые углы (a и b) из ряда чисел(m6, m7 и m8), которые являются тригонометрическими функциями, применяемыми к этим углам (как показано в комментариях к коду), затем я инвертирую эти углы для восстановления m6, m7 и m8 и сравнивая их с исходными числами, которые я ожидал сопоставить с 14-й или 15-й цифрой, поскольку я использую double числа.Однако, как вы можете видеть из результатов, есть некоторые числовые различия, которые я не могу объяснить для случаев 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;

}

1 Ответ

4 голосов
/ 17 июня 2019

Как правило, любые ошибки в тригонометрических функциях, которые поставляются как стандартная реализация библиотеки C, которые находятся в восьмом значимом значении, следует рассматривать как нормальные. (По моему опыту, реализации работают с sin и cos лучше, чем с tan, и это также относится к инверсиям.)

Ни в стандарте C, ни в спецификациях IEEE754 с плавающей запятой (общая схема, принятая в C с плавающей запятой) не требуется, чтобы эти функции были такими же точными, как и типы данных, которые они используют (ср. sqrt или арифметические операторы + , -, * и /, которые требуются IEEE754 для получения наилучшего возможного результата). И очень много реализаций имеют большую скорость выполнения, чем точность.

Если вам нужна более высокая точность, вам нужно переключить эти функции на те, которые гарантируют лучшие результаты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...