Неверные результаты тригонометрических функций математической библиотеки C++

Сейчас я работаю над личным проектом, которым занимаюсь уже почти год. Я пытаюсь перенести его в среду Windows, и мне это удалось. Поскольку я пытаюсь в ближайшее время предоставить людям версию для Windows, я решил продолжить разработку в Windows, пытаясь добавить новые функции и устранить ошибки, которые существовали в течение нескольких месяцев. Недавно пытаясь добавить функциональность, которая сильно зависит от тригонометрии, я обнаружил, что все 3 тригонометрические функции, как ни странно, возвращают одно и то же значение (1072693887) независимо от переданного параметра. Как вы понимаете, это приводит к довольно странным ошибкам в системе.

У меня есть math.h, и, насколько мне известно, нет других файлов, содержащих эту функцию. (Возможно, есть команда отладчика, чтобы найти, где определен символ? Я не смог найти ничего подобного, но, возможно, я что-то пропустил.) Я пытался спросить в другом месте и поискать в Google, но безрезультатно...

Кто-нибудь еще слышал об этой проблеме раньше или знает, как ее исправить?


person Morgan Patch    schedule 20.11.2011    source источник
comment
Как насчет показать код?   -  person    schedule 20.11.2011
comment
Что означает число, которое вы передаете?   -  person FailedDev    schedule 20.11.2011


Ответы (4)


Все, что я знаю, это то, что GDB сообщает мне, что результатом этого является 1072693887, что это происходит со всеми тремя моими триггерными функциями (и что дуговые версии всех трех из них просто возвращают -1072693887) независимо от того, какой параметр я передаю.

Возможно, проблема в GDB. Что произойдет, если вы просто вручную выведете значения на консоль?

person fredoverflow    schedule 20.11.2011
comment
Хотел бы я ответить на этот вопрос... По какой-то причине, несмотря на то, что Code::Blocks настроен для работы в качестве консольного приложения, ни один из моих вызовов std::cout или printf на самом деле не отображается... - person Morgan Patch; 21.11.2011
comment
Тогда у вас есть гораздо более серьезные проблемы, чем проблемы с округлением. Что произойдет, если вы вставите строку std::cin.peek(); в самый конец строки main? - person fredoverflow; 21.11.2011
comment
Итак, консоль открывается, и я получаю команду «Нажмите любую клавишу для продолжения» в конце выполнения... Но независимо от того, запускаю ли я свой код из Code::Blocks или просто открываю cmd.exe и запускаю свою программу, в любом случае я не получаю никакого вывода, несмотря на то, что в моем коде есть вызовы std::cout... И это происходит только в Windows... - person Morgan Patch; 21.11.2011
comment
Хорошо, я только что проверил это и на Linux... Видимо, это просто проблема с моим отладчиком, потому что мне удалось заставить там выполняться мои вызовы std::cout, и он действительно сказал мне правильный цифры... вздох В любом случае спасибо за помощь... - person Morgan Patch; 21.11.2011

РЕДАКТИРОВАТЬ: этот ответ не актуален. Смотрите комментарии.


Вероятно, это связано с численной нестабильностью.

Когда вы передаете такое большое значение в sin(), cos() или любую из периодических триггерных функций, вы должны помнить, что существует неявное значение по модулю на 2*pi.

Если вы используете float, то неопределенность 1072693887 намного больше, чем 2*pi. Поэтому какой бы результат вы ни получили, это мусор.

Однако нам нужно увидеть некоторый код, чтобы точно увидеть, что происходит.

EDIT: Вот иллюстрация:

sin(1072693886) =  0.6783204666
sin(1072693887) = -0.2517863119
sin(1072693888) = -0.9504019164

Но если тип данных float, то неопределенность 1072693887 равна +/- ~64...

person Mysticial    schedule 20.11.2011
comment
Возможно, я должен был быть более ясным... Если я ввожу значение, скажем, PI/3 (для которого значение должно быть квадратным корнем из 3 или приблизительно 0,866), я получаю 1072693886 в качестве возвращаемого значения из функции триггера. . - person Morgan Patch; 20.11.2011
comment
Тогда это звучит как явная ошибка в вашем коде. Разместите свой код, чтобы мы могли взглянуть на него. В противном случае мы не сможем помочь. - person Mysticial; 20.11.2011

1072693887 — это 3FF207FF в шестнадцатеричном формате, что соответствует 1,8908690 в IEEE одинарной точности с плавающей запятой. Вы уверены, что ваша проблема связана не только с представлением, т.е. вы выполняете кастинг или просматриваете результат как целое число?

person talonmies    schedule 20.11.2011
comment
Все, что я знаю, это то, что GDB сообщает мне, что результатом этого является 1072693887, что это происходит со всеми тремя моими триггерными функциями (и что дуговые версии всех трех из них просто возвращают -1072693887) независимо от того, какой параметр я передаю. Даже если то, что вы говорите, правда, все равно кажется явной ошибкой. - person Morgan Patch; 20.11.2011
comment
Так что опубликуйте репродукцию, показывающую, что вы делаете, иначе все, что вы получите, это дикие догадки. Математическая библиотека gnu чрезвычайно хорошо протестирована и используется буквально в миллионах приложений, где результаты подвергаются самой тщательной проверке, вероятность того, что вы нашли ошибку, исчезающе мала. - person talonmies; 20.11.2011

Математическая библиотека в порядке.

Вы понимаете, что функции ожидают радианы в качестве входных данных, верно?

E.g. :

double param = 90.0;
double rads = param * M_PI/180;
std::cout << std::fixed << "Angle : " << param << " sin : " << sin (rads) << " cos " << cos(rads);

Выход :

Angle : 90.000000 sin : 1.000000 cos 0.000000-0.304811
person FailedDev    schedule 20.11.2011
comment
Это правда, и это причина многих (большинства?) жалоб math.h не работает, но симптомом являются случайные кажущиеся результаты, а не одно последовательное значение. - person dmckee --- ex-moderator kitten; 20.11.2011
comment
Прежде всего, я ввожу радианы. Во-вторых, даже если я ошибочно ввел градусы, диапазон sin и cos равен 1 (даже если tan имеет бесконечный диапазон). sin любого числа и cos любого числа все равно не должны возвращать 1072683887. - person Morgan Patch; 20.11.2011
comment
@drummerp Опубликуйте минимальный образец кода, который воспроизводит это. В противном случае мы можем только гадать. - person FailedDev; 20.11.2011
comment
Хм... Это интересно. Я попытался создать новый проект, чтобы протестировать его, с одним файлом, выглядящим так: #include <iostream> #include <math.h> using namespace std; int main() { cout << "The sin of 30 degrees is: " << sin(30 * (M_PI / 180)) << endl; return 0; } На самом деле он вернул 0,5. - person Morgan Patch; 20.11.2011
comment
@drummerp Так что ошибка кроется где-то еще :) - person FailedDev; 20.11.2011
comment
Я не могу представить, где, хотя... Я никогда сознательно не включал ничего, что имеет другие функции с таким именем... И даже если бы я это сделал, не стал бы мой компилятор жаловаться на двусмысленное использование sin? Поскольку я знаю, что включаю math.h, не будет ли тот факт, что он компилируется и запускается, указывать на то, что он должен использовать триггерные функции в math.h? - person Morgan Patch; 20.11.2011
comment
@drummerp, попробуйте включить math.h в пространство имен, чтобы вы могли изолировать его и протестировать. - person nullpotent; 20.11.2011
comment
@drummerp Попробуйте заменить свой sin в коде на ::sin(...). - person FailedDev; 20.11.2011
comment
@drummerp: если вы используете C++, включите <cmath> вместо <math.h>. - person Blastfurnace; 20.11.2011
comment
Я изменил его на ‹cmath›. Теперь он говорит, что ответ 1071645311. Я попробую решение ::sin... РЕДАКТИРОВАТЬ: использование оператора глобального пространства имен тоже не помогло... - person Morgan Patch; 20.11.2011