Программистское

Dec 14, 2013 23:17

Далее под катом немного кода на СИ и одна проблема. Если у вас есть немного свободного времени и вы программист, то я буду очень рад помощи.
Помочь... )

Leave a comment

Comments 24

birdwatcher December 14 2013, 19:40:29 UTC
Обычно так бывает из-за того, что в программе есть неинициализированные переменные, в которых на разных машинах оказывается разный мусор. Тем не менее, the IEEE standard does not guarantee that the same program will deliver identical results on all conforming systems, так что, если вы работаете с хаосом, где это и должно происходить, то, может, вам как раз удалось сконструировать именно тот пример, где результаты должных быть совсем другие. Есть возможность запостить программу целиком?

Reply

goliafffff December 14 2013, 19:46:36 UTC
Спасибо, что откликнулись.

Код программы довольно большой. Там много функций, и чтобы понять принцип их работы нужно иметь представление об одной математической теории. И, да, возможно есть пара неинициализированных переменных, но я ими не пользуюсь.

И спасибо за ссылку.

Reply

birdwatcher December 14 2013, 20:06:16 UTC
Попробуйте откомпилировать с выводом абсолютно всех диагностик (в gcc, например, флаги -Wall -Wextra)

Reply

goliafffff December 15 2013, 06:30:16 UTC
Так я уже делал. Компилятор говорит, что в трёх функциях есть неиспользованные переменные, но при решении этой задачи я не обращаюсь к этим функциям вообще.

Reply


freddy_lj December 14 2013, 20:46:03 UTC
Вроде как аппаратной реализации тригонометрических функций в современных процессорах для персоналок нет.

Немного работал с Фортраном. Там возможны сюрпризы с ключами компилятора при оптимизации под конкретный процессор, есть ключи при которых скорость выполнения арифметических операций увеличивается за счет нарушения стандарта IEEE.

Reply

ex_juan_gan December 14 2013, 21:41:04 UTC
Есть, в FPP. Через ряд. 32 бита точность почему-то.

Reply

freddy_lj December 15 2013, 11:04:46 UTC
Точность вещественных арифметических вычислений задается в коде. Наиболее распространенными являются одинарная точность (float, 32 двоичных разряда) и двойная точность (double, 64 разряда). Есть еще увеличенная (80 разрядов) и половинная (16). С заданием типов переменных, аргументов, констант из-за этого приходится быть аккуратным. Вроде здесь немного описано, касательно тригонометрических функций http://msdn.microsoft.com/ru-ru/library/wkbss70y.aspx

Есть вопрос как именно в коде или в конкретном компиляторе определяется константа M_PI.

Reply


ex_juan_gan December 14 2013, 21:39:10 UTC
Ну хм, не знаю, во-первых, не так уж точно этот синус вычисляется на FPP, во-вторых, есть четыре режима округления; в-третьих, вас что, устраивают неустойчивые решения? А смысл? Вы тогда зависите от ошибок округления, это не хаос, а обычные ошибки.

Я хочу сказать, что вы экспериментируете, похоже, не с математикой, а со случайным кодом. Не очень понимаю, что в этом может быть интересного, и какая в этом может быть сермяжная правда.

Например, 3.14/10.0 уже достаточно, чтобы внести в вычисления произвольную чушь.
Потому что не делится на двоичных машинах.

Чего вы хотите добиться-то?

Reply

goliafffff December 15 2013, 06:49:02 UTC
По-моему очевидно, что ошибки меня не устраивают - иначе не писал бы этот пост. И мне тоже кажется, что проблема с кодом, а не с исследуемой моделью. Но также вполне естественно, что при анализе происходящего и поиске ошибок, я принимаю во внимание свойства исследуемой системы. Естественно, что хочется получить работающий код, который на разных компьютерах даёт одинаковый результат ( ... )

Reply

pphantom December 15 2013, 11:18:07 UTC
При вычислении 3.14/10.0*ds.t возникают ошибки округления (число 3.14 непредставимо в виде конечной двоичной дроби), и результат "прыгает" в зависимости от того, в какую сторону будет округляться итог. А Вы в результате изучаете особенности не отображения, а архитектуры компьютера. :)

Собственно, это предположение можно легко проверить. Я соорудил программку, которая считает первое отображение (в котором никаких синусов нет), но с разной точностью (двойной и четверной). Разница результатов начинается, естественно, с 10^{-16}, но уже за несколько десятков итераций доходит до 10^0.

Так что Вам просто повезло - первое отображение все используемые компьютеры считают одинаково (и, по-видимому, одинаково неверно). Во втором же случае появляются какие-то мелкие различия, которые приводят к разным результатам.

Reply

ex_juan_gan December 15 2013, 17:25:07 UTC
FPP, последний раз, когда я это исследовал, давал всего 32 бита мантиссы на тригонометрических функциях.
Четыре режима округления (ими можно управлять) - это к плюс бесконечности, к минус бесконечности, к нулю, к ближайшему чётному.

Вы делите на 10, т.е. на 2 и на 5. На 2 делить ошибки нет, а на 5 деление получается неточное, потому что это не степерь двойки, дробь бесконечная. и там остаток отбрасывается.

Reply


_winnie December 27 2013, 08:45:06 UTC
Да, в целях сохранения душевного здоровья - лучше считать что в разных "системах" - разные синусы. Под "системами" я понимаю связку не просто процессор, а связку процессор+математическая библиотека+компилятор.

Это можно победить, но лучше считать что они разные.

Ну да, динамические ситесмы они такие, но как бы и не страшно - погрешность измерительных приборов гораздо больше, чем погрешность double. Есть ещё более страшная проблема - погрешность модели. Если вы эмулируете физический процесс, то вы не учли ветер, изменение гравитации от высоты, или ещё что-нибудь.

Reply

goliafffff December 27 2013, 16:44:45 UTC
У меня тут больше математическая задача. Если в аргументе синуса стоит M_PI/30.0*ds.t, то я получаю различные результаты. Если же заменить M_PI/30.0 на приблизительное 0.10471975511966, то всё встаёт на свои места. На сколько я понимаю корень зла кроется в ошибки округления при делении на 30.0.

Как это можно победить?

Reply

_winnie December 27 2013, 17:37:45 UTC
В общем случае множество действительных чисел в один double не засунешь.
Нужно вдумываться в конкретную задачу.

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

Например, с точки зрения double ( cos(0.00000001) - 1 ) в точности равно нулю, но это не значит что 0.00000001 -- неподвижная точка для (cos(x)-1+x)

Reply

birdwatcher December 27 2013, 17:47:06 UTC
Я согласен с аргументом про общий случай, но данный случай очень частный. Если я правильно понял автора, он сводится к разному поведению деления на двух разных ieee-совместимых машинах. Я бы безусловно ожидал побитового совпадения. А сейчас бы, соответственно, распечатывал двоичное представление М_PI / 30.0 в обоих случаях.

Reply


Leave a comment

Up