Далее под катом немного кода на СИ и одна проблема. Если у вас есть немного свободного времени и вы программист, то я буду очень рад помощи. ( Помочь... )
Да, в целях сохранения душевного здоровья - лучше считать что в разных "системах" - разные синусы. Под "системами" я понимаю связку не просто процессор, а связку процессор+математическая библиотека+компилятор.
Это можно победить, но лучше считать что они разные.
Ну да, динамические ситесмы они такие, но как бы и не страшно - погрешность измерительных приборов гораздо больше, чем погрешность double. Есть ещё более страшная проблема - погрешность модели. Если вы эмулируете физический процесс, то вы не учли ветер, изменение гравитации от высоты, или ещё что-нибудь.
У меня тут больше математическая задача. Если в аргументе синуса стоит M_PI/30.0*ds.t, то я получаю различные результаты. Если же заменить M_PI/30.0 на приблизительное 0.10471975511966, то всё встаёт на свои места. На сколько я понимаю корень зла кроется в ошибки округления при делении на 30.0.
Я согласен с аргументом про общий случай, но данный случай очень частный. Если я правильно понял автора, он сводится к разному поведению деления на двух разных ieee-совместимых машинах. Я бы безусловно ожидал побитового совпадения. А сейчас бы, соответственно, распечатывал двоичное представление М_PI / 30.0 в обоих случаях.
Надеюсь, что вычисляется на этапе компиляции! Кстати, будет смешно, если окажется, что деление в собственном коде работает правильно, а в кодогенераторе сломано.
Логика рассуждений мне понятна, но, честно говоря, я не знаю как посмотреть сгенерированный машинный код или результат работы препроцессора. Вообще очень странно, что на разных компьютерах разный результат. Просто если дело в округлении результата деления M_PI на 30, то в рамках моей задачи это будет означать немного другую частоту в системе, и статистические характеристики, которые я считаю могут, измениться (и то не сильно) количественно, но должны подчиняться теоретической закономерности. Не понятно почему при задании частоты через M_PI/30.0 появляется систематическая погрешность.
Это будет обычный C, в котором развернуты все #include, #define, #if и проч. Вместо M_PI будет стоять число в десятичной записи, надо убедиться, что оно одинаковое на двух машинах.
На последний вопрос, ничего не зная про задачу, ничего путного не отвечу.
1) Есть библиотеки и программы для расчетов с произвольной точностью. "произвольная" не значит "бесконечная". Т.е. вам допустим нужен результат с точностью до 22 знаков после запятой. Вы опытным путём или на бужаке понимаете, что для этого достаточно 1000 знаков (или 10000) после запятой, ну и считаете с такой точностью.
2) Есть библиотеки для символьных вычислений, которые преобразуют формулы, а не числа.
Подходит это или нет - зависит от задачи. Может реорганизацией вычислений хватит и double, а может у вас хаотическая система, которой и "произвольной" точности не хватит (ну невозможно иррациональное число приблизить какой-то точностью), или мощности символьных вычислений не хватит (например, попробуйте доказать что последовательность n = (n mod 2 == 0) ? n/2 : 3n*1 сходится к 1 для всех целых n).
И возможно, использовал бы не C, а привычную нотацию в 2) калькуляторе bc 3) python и а) его модуль decimal (только sin/cos нужно будет считать самому) б) библиотека sympy (помимо расчетов произвольной точности, она умеет символьные вычисления, типа sympy.summation(1/(n*n), (n, 1, oo)) равно pi**2/6 ) в) библиотека mpmath
Могу переписать ваш сишный код на python по доллару за строчку :)
Это можно победить, но лучше считать что они разные.
Ну да, динамические ситесмы они такие, но как бы и не страшно - погрешность измерительных приборов гораздо больше, чем погрешность double. Есть ещё более страшная проблема - погрешность модели. Если вы эмулируете физический процесс, то вы не учли ветер, изменение гравитации от высоты, или ещё что-нибудь.
Reply
Как это можно победить?
Reply
Нужно вдумываться в конкретную задачу.
Вычислениями на компьютере можно проверить, что два выражения очень близки, но невозможно доказать что два выражения в точности равны.
Например, с точки зрения double ( cos(0.00000001) - 1 ) в точности равно нулю, но это не значит что 0.00000001 -- неподвижная точка для (cos(x)-1+x)
Reply
Reply
Reply
Reply
Reply
Reply
http://stackoverflow.com/questions/5034209/how-do-i-see-what-a-file-looks-like-after-preprocessing
Это будет обычный C, в котором развернуты все #include, #define, #if и проч. Вместо M_PI будет стоять число в десятичной записи, надо убедиться, что оно одинаковое на двух машинах.
На последний вопрос, ничего не зная про задачу, ничего путного не отвечу.
Reply
1) Есть библиотеки и программы для расчетов с произвольной точностью. "произвольная" не значит "бесконечная". Т.е. вам допустим нужен результат с точностью до 22 знаков после запятой. Вы опытным путём или на бужаке понимаете, что для этого достаточно 1000 знаков (или 10000) после запятой, ну и считаете с такой точностью.
2) Есть библиотеки для символьных вычислений, которые преобразуют формулы, а не числа.
Подходит это или нет - зависит от задачи. Может реорганизацией вычислений хватит и double, а может у вас хаотическая система, которой и "произвольной" точности не хватит (ну невозможно иррациональное число приблизить какой-то точностью), или мощности символьных вычислений не хватит (например, попробуйте доказать что последовательность n = (n mod 2 == 0) ? n/2 : 3n*1 сходится к 1 для всех целых n).
Reply
Reply
Я бы почитал такое -
1) http://stackoverflow.com/questions/4486882/whats-the-best-for-speed-arbitrary-precision-library-for-c
И возможно, использовал бы не C, а привычную нотацию в
2) калькуляторе bc
3)
python и
а) его модуль decimal (только sin/cos нужно будет считать самому)
б) библиотека sympy (помимо расчетов произвольной точности, она умеет символьные вычисления, типа sympy.summation(1/(n*n), (n, 1, oo)) равно pi**2/6 )
в) библиотека mpmath
Могу переписать ваш сишный код на python по доллару за строчку :)
Reply
Reply
Leave a comment