Насколько детерминированный погрешность с плавающей точкой?

25
задан dmckee 14 February 2010 в 05:12
поделиться

8 ответов

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

Определенные глюки, о которых я знаю:

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

2.) промежуточные результаты с плавающей точкой часто используют точность на 80 битов в регистре, но только 64 бита в памяти. Если программа перекомпилирована способом, который изменяет регистр, движущийся потоком в функции, это может возвратить различные результаты по сравнению с другими версиями. Большинство платформ даст Вам способ вызвать все результаты быть усеченным к в точности памяти.

3.) стандартные библиотечные функции могут измениться между версиями. Я заключаю, что существуют некоторые весьма примеры, с которыми обычно встречаются, этого в gcc 3 по сравнению с 4.

4.) Сам IEEE позволяет некоторым двоичным представлениям отличаться... конкретно значения NaN, но я не могу вспомнить детали.

20
ответ дан Mitch Wheat 28 November 2019 в 20:45
поделиться

Короткий ответ - то, что вычисления FP совершенно детерминированы, согласно Стандарт Плавающей точки IEEE , но это не означает, что они совершенно восстанавливаемы через машины, компиляторы, ОС, и т.д.

длинный ответ на эти вопросы, и больше может быть найдено в том, что является, вероятно, лучшей ссылкой на плавающей точке, David Goldberg , Что Каждый Программист Должен Знать Об Арифметике С плавающей точкой . Пропустите к разделу по стандарту IEEE для ключевых деталей.

Для ответа на пункты маркированного списка кратко:

  • Время между вычислениями и состоянием ЦП имеют мало общего с этим.

  • Аппаратные средства могут влиять на вещи (например, некоторые GPU не являются совместимой плавающей точкой IEEE).

  • Язык, платформа и ОС могут также влиять на вещи. Для лучшего описания этого, чем я могу предложить, видеть ответ Jason Watkins. Если Вы используете Java, смотрите на Kahan напыщенная речь на несоответствиях Java с плавающей точкой .

  • Солнечные вспышки могли бы иметь значение, надо надеяться, нечасто. Я не волновался бы слишком много, потому что, если они действительно имеют значение, тогда все остальное завинчено также. Я поместил бы это в ту же категорию как волнение [приблизительно 113] EMP.

Наконец при выполнении того же последовательность из вычислений с плавающей точкой на тех же начальных исходных данных, тогда вещами должен быть replayable точно очень хорошо. Точная последовательность может измениться в зависимости от Вашей библиотеки компилятора/OS/стандарта, таким образом, Вы могли бы получить некоторые небольшие ошибки этот путь.

то, Где Вы обычно сталкиваетесь с проблемами в плавающей точке, - то, если у Вас есть численно нестабильный метод, и Вы запускаете с исходных данных FP, которые являются [приблизительно 115] то же, но не совсем. Если конюшня Вашего метода, необходимо быть в состоянии гарантировать воспроизводимость в рамках некоторого допуска. Если Вы хотите больше детали, чем это, то смотрите на статью FP Goldberg, связанную выше, или забираете вводный текст согласно числовому анализу.

17
ответ дан Todd Gamblin 28 November 2019 в 20:45
поделиться

Я думаю, что Ваш беспорядок находится в типе погрешности вокруг плавающей точки. Большинство языков реализует стандарт плавающей точки IEEE , Этот стандарт размечает, как отдельные биты в плавающем/двойном используются для создания числа. Обычно плавание состоит из четырех байтов и двойных восьми байтов.

А mathmatical операция между двумя числами с плавающей точкой будет иметь то же значение каждым разом (как определено в рамках стандарта).

погрешность существует точности. Рассмотрите интервал по сравнению с плаванием. Оба обычно поднимают то же число байтов (4). Все же максимальное значение, которое может сохранить каждое число, дико отличается.

  • интервал: примерно 2 миллиарда
  • плавание: 3.40282347E38 (вполне немного больше)

различие находится в середине. интервал, может представить каждое число между 0 и примерно 2 миллиарда. Плавание однако не может. Это может представить 2 миллиарда значений между 0 и 3.40282347E38. Но это оставляет целый диапазон значений, которые не могут быть представлены. Если математическое уравнение поражает одно из этих значений, это нужно будет закруглить к представимому значению и следовательно считают "неточным". Ваше определение неточных может варьироваться:).

8
ответ дан Mitch Wheat 28 November 2019 в 20:45
поделиться

Кроме того, в то время как Goldberg является большой ссылкой, оригинальный текст является также неправильным: IEEE754 не является gaurenteed, чтобы быть портативен . Я не могу подчеркнуть это достаточно данное, как часто этот оператор сделан на основе просматривания текста. Более поздние версии документа включают раздел, который обсуждает это конкретно :

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

4
ответ дан Jason Watkins 28 November 2019 в 20:45
поделиться

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

, Если погрешность является значительной к тому, что Вы делаете тогда, необходимо искать различный алгоритм.

Вы говорите, что, если вычисления не точны, ошибки в запуске могут иметь огромные последствия к концу моделирования.

, Что мой друг не является моделированием. Если Вы получаете чрезвычайно различные результаты из-за крошечных различий из-за округления и точности тогда, возможности состоят в том, что ни один из результатов не имеет законности. Просто, потому что можно повторить, что результат больше не делает его допустимым.

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

2
ответ дан Dipstick 28 November 2019 в 20:45
поделиться

HM. Начиная с OP, который попросили C#:

JIT байт-кода C# детерминирован, или он генерирует различный код между различными выполнениями? Я не знаю, но я не доверял бы Монете в пять центов.

я мог думать о сценариях, где JIT имеет некоторые функции качества обслуживания и решает провести меньше времени на оптимизации, потому что ЦП делает, тяжелое перемалывание чисел где-то в другом месте (думайте фоновое кодирование DVD)? Это могло привести к тонким различиям, которые могут привести к огромным различиям позже.

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

1
ответ дан Nils Pipenbrinck 28 November 2019 в 20:45
поделиться

Очень немного FPUs соответствуют стандарту IEEE (несмотря на их требования). Так запущение той же программы в различных аппаратных средствах действительно даст Вам различные результаты. Результаты, вероятно, будут в угловых случаях, которых необходимо уже избежать как часть использования FPU в программном обеспечении.

ошибки IEEE часто исправляются в программном обеспечении, и действительно ли Вы уверены, что операционная система, которую Вы выполняете сегодня, включает надлежащие прерывания и патчи от производителя? Что относительно прежде или после того, как ОС имеет обновление? Все ошибки удалены и добавленные исправления ошибок? Компилятор C в синхронизации со всем этим и компилятор C, производит надлежащий код?

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

Наблюдают правило номер 1 FP: Никогда не используйте если (что-то == что-то) сравнение. И правило номер два IMO имело бы отношение к ASCII к fp или fp к ASCII (printf, scanf, и т.д.). Существует больше проблем точности и ошибки там, чем в аппаратных средствах.

С каждым новым поколением аппаратных средств (плотность) влияние от солнца более очевидно. У нас уже есть проблемы с SEU's на поверхности планет, настолько независимой от вычислений с плавающей точкой, у Вас будут проблемы (немного поставщиков потрудились заботиться, поэтому ожидайте катастрофические отказы чаще с новыми аппаратными средствами).

Путем потребления огромных сумм логики fpu, вероятно, будет очень быстрым (единственный такт). Не немного медленнее, чем целое число alu. Не путайте это с современным fpus, являющимся столь же простым, как alus, fpus являются дорогими. (alus аналогично используют больше логики для, умножаются и делятся для снижения этого к одному такту, но совсем не столь же большому как fpu).

Придерживаются простых правил выше, изучают плавающую точку немного больше, понимают бородавки и прерывания, которые идут с нею. Можно хотеть проверить на бесконечность или nans периодически. Ваши проблемы, более вероятно, будут найдены в компиляторе и операционной системе, чем аппаратные средства (в целом не только fp математика). Современные аппаратные средства (и программное обеспечение), в эти дни, по определению полны ошибок, поэтому просто попытайтесь быть меньшим количеством багги, чем, на чем работает Ваше программное обеспечение.

-4
ответ дан old_timer 28 November 2019 в 20:45
поделиться

Этот ответ в FAQ по C ++, вероятно, описывает его лучше всего:

http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.18

Это не только разные Архитектура или компилятор могут доставить вам проблемы, числа с плавающей запятой уже ведут себя странным образом в одной и той же программе. Как указано в FAQ, если y == x истинно, это все равно может означать, что cos (y) == cos (x) будет ложным. Это связано с тем, что процессор x86 вычисляет значение с 80-битным значением, в то время как значение хранится как 64-битное в памяти, поэтому вы в конечном итоге сравниваете усеченное 64-битное значение с полным 80-битным значением.

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

С практической точки зрения, это не так уж плохо, я мог бы воспроизвести простую математику с указанием числа с плавающей запятой с другой версией GCC на 32-битной версии Linux для бит, но в тот момент, когда я перешел на 64-битный Linux, результат был уже не тот. Демонстрационные записи, созданные на 32-битной системе, не будут работать на 64-битной и наоборот, но будут работать нормально при запуске на той же архитектуре.

2
ответ дан 28 November 2019 в 20:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: