64-разрядные числа с плавающей точкой ведут себя тождественно на всех современных ПК?

Я хотел бы знать, могу ли я предположить, что те же самые операции на тех же 64-разрядных числах с плавающей точкой дают точно те же результаты на каком-либо современном ПК и на наиболее распространенных языках программирования? (C++, Java, C#, и т.д.). Мы можем принять, которым мы управляем на числах, и результатом является также число (никакой NaNs, INFs и так далее).

Я знаю, что существует два очень подобных стандарта вычисления с помощью чисел с плавающей точкой (IEEE 854-1987 и IEEE 754-2008). Однако я не знаю, как это на практике.

10
задан mskfisher 9 May 2012 в 19:58
поделиться

7 ответов

Современные процессоры, которые реализуют 64-битные плавающие-точки, как правило, реализуют то, что близко к стандарту IEEE 754-1985, недавно вытесненные стандартом 754-2008.

Стандарт 754 указывает, какой результат вы должны получить от определенных основных операций, особенно добавляющих, вычитание, умножение, разделение, квадратный корню и отрицание. В большинстве случаев числовой результат указан именно: результатом должен быть представимый номер, который ближе всего к точному математическому результату в направлении, указанном в режиме округления (к ближайшему, к бесконечности, к нулю или к негативной бесконечности). В режиме «До ближайшего» стандарт также указывает, как сломаны галстуки.

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

Однако есть несколько вопросов, которые мешают получать идентичные результаты на разных процессорах. Одним из них является то, что компилятор часто свободен реализовать последовательности операций с плавающей точкой различными способами. Например, если вы пишете «A = B C + D» в C, где все переменные объявлены двойным, компилятор свободен вычислить «B C» в одноточной арифметике, либо что-то с более чем диапазон или точность. Если, например, процессор имеет регистры, способные удерживать количество плавающих точек с плавающей точкой расширенной точностью, и выполнение арифметики с расширенной точкой не требует большего количества процессоров, чем выполнение арифметики с двойной точкой, компилятор может генерировать код с использованием расширенного -точность. На таком процессоре вы можете не получить те же результаты, что и вы на другом процессоре. Даже если компилятор делает это регулярно, он может не в некоторых обстоятельствах, потому что регистры заполнены во время сложной последовательности, поэтому она временно хранит промежуточные результаты в памяти временно. Когда это делает это, он может написать только 64-битный двойной, а не номер расширенного точности. Таким образом, рутина, содержащая арифметику с плавающей точкой, может дать разные результаты только потому, что она была скомпилирована с другим кодом, возможно, включена в одном месте, а компилятор нужны регистры для чего-то другого.

Некоторые процессоры имеют инструкции по вычислинию умножения и добавления в одну инструкцию, поэтому «B C + D» могут быть вычислены без промежуточного округа и получить более точный результат, чем на процессоре, который первый вычисляет B C а затем добавляет d.

Ваш компилятор может иметь коммутаторы для управления поведением.

Есть несколько мест, где стандарт 754-1985 не требует уникального результата. Например, при определении того, произошло ли предпринятое, а результат слишком мал, чтобы быть точно представленным точным), стандарт позволяет внедрять определение либо до, либо после того, как он расторгнет показатель (доля доли) к целевой точности. Таким образом, некоторые реализации скажут вам, что onlowflow произошел, когда не будут.

Общая особенность в процессорах состоит в том, чтобы иметь режим «почти IEEE 754», который устраняет трудности с недовольством, заменяя ноль вместо того, чтобы возвращать очень небольшое число, которое требует стандарта. Естественно, вы получите разные номера при выполнении в таком режиме, чем при выполнении в более совместимом режиме. Несоведочный режим может быть установлен по умолчанию для вашего компилятора и / или операционной системы по причинам производительности.

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

Когда вы переходите за пределы основных арифметических операций в такие вещи, как синус и косинус, вы очень зависимы от используемой библиотеки. Трансцендентные функции обычно рассчитываются с тщательно спроектированными приближениями. Реализации разработаны независимо различными инженерами и получают разные результаты друг от друга. В одной системе функция SIN может дать точные результаты в пределах ULP (единица измерения наименьших прецизионов) для небольших аргументов (меньше, чем Pi или SO), но большие ошибки для больших аргументов. В другой системе функция SIN может дать точные результаты в нескольких ULP для всех аргументов. Никакой текущей математической библиотеки не известен правильно округлыми результатами для всех входов. Существует проект, Crlibm (правильно округлая LIBM), который сделал некоторую хорошую работу по этой цели, и они разработали реализации для значительных частей математической библиотеки, которые правильно округлые и имеют хорошую производительность, но не все в библиотеке математики еще.

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

8
ответ дан 3 December 2019 в 19:33
поделиться

Если вы имеете в виду получить точно такой же результат, то ответ нет.

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

(Это может произойти, например, на компьютере с процессором Intel Intel, если оптимизатор сохраняет переменную для промежуточного результата в реестре, который хранится в памяти в неотпускательной сборке. Так как регистры Intel FPU составляют 80 бит и двойной Переменные составляют 64 бита, промежуточный результат будет храниться с большей точностью в оптимизированной сборке, вызывая разные значения в более поздних результатах.).

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

7
ответ дан 3 December 2019 в 19:33
поделиться

Одинаковая программа C # может выявлять различные численные результаты на одном и том же ПК, однажды скомпилированным в режиме отладки без оптимизации, второй раз скомпилирован в режиме выпуска с оптимизацией включено. Это мой личный опыт. Мы не рассматривали это, когда настроили автоматическую регрессию для тестового набора для одной из наших программ впервые, и были полностью удивлены, что многие наши тесты не удалось без каких-либо очевидных причин.

1
ответ дан 3 December 2019 в 19:33
поделиться

Предполагая, что вы говорите о применении нескольких операций, я не думаю, что вы получите точные номера. Архитектура CPU, использование компилятора, настройки оптимизации изменит результаты ваших вычислений.

Если вы имеете в виду точный порядок операций (на уровне сборки), я думаю, что вы все равно получите вариации. Для примера чипсы Intel Intel используют расширенные прецизионные (80 битов) внутри, что может быть не в корпусе для других процессоров. (Я не думаю, что расширенная точность обязательна)

1
ответ дан 3 December 2019 в 19:33
поделиться

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

2
ответ дан 3 December 2019 в 19:33
поделиться

Для 64-битного типа данных я знаю только из «двойную точность» / «Binare64» от IEEE 754 (1985 и 2008 гг. Для общих случаев) используется используется.

Примечание. Типы Radix, определенные в IEEE 854-1987, должны быть заменены IEEE 754-2008 в любом случае.

0
ответ дан 3 December 2019 в 19:33
поделиться

Для C# на x86 используются 80-битные регистры FP.

В стандарте C# сказано, что процессор должен работать с той же точностью, что и сам тип, или больше (т.е. 64-битный в случае 'double'). Допускаются акции, за исключением хранения. Это означает, что локальные и параметры могут быть с точностью выше 64 бит.

Другими словами, приписывание переменной-члену локальной переменной может (и фактически будет при определенных обстоятельствах) быть достаточным для того, чтобы дать неравенство.

См. также: Float/double precision в режимах отладки/освобождения

1
ответ дан 3 December 2019 в 19:33
поделиться
Другие вопросы по тегам:

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