Когда я должен использовать ключевое слово strictfp в Java? - PullRequest
241 голосов
/ 06 февраля 2009

Я посмотрел, что это делает, но есть ли у кого-нибудь пример, когда вы будете использовать ключевое слово strictfp в Java? Кто-нибудь на самом деле нашел применение для этого?

Будут ли какие-либо побочные эффекты от того, что я просто добавлю это на все мои операции с плавающей запятой?

Ответы [ 8 ]

258 голосов
/ 06 февраля 2009

Strictfp гарантирует, что вы получите точно такие же результаты от ваших вычислений с плавающей запятой на каждой платформе. Если вы не используете strictfp, реализация JVM может использовать дополнительную точность там, где она доступна.

Из JLS :

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

Другими словами, это означает, что Write-Once-Run-Anywhere фактически означает Write-Once-Get-Equally-Wrong-Results-Everywhere .

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

60 голосов
/ 06 февраля 2009

В Википедии есть хорошая статья на эту тему здесь со ссылкой на спецификацию Java.

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

Так зачем вам использовать strictfp? Один сценарий, который я вижу, - это распределенное приложение (или многопользовательская игра), где все вычисления с плавающей точкой должны быть детерминированными, независимо от того, какое аппаратное обеспечение или процессор используется. Какой компромисс? Наиболее вероятное время выполнения.

22 голосов
/ 14 июля 2015

Все началось с истории,

Когда java разрабатывался Джеймсом Гослингом, Гербертом и остальной его командой. Они имели в виду эту сумасшедшую вещь под названием независимость от платформы . Они хотели сделать oak (Java) настолько лучше, что он будет работать точно так же на любой машине с другим набором команд, даже с разными операционными системами. Но возникла проблема с десятичными числами, также известными как языки с плавающей запятой и double в языках программирования. Некоторые машины были построены нацелены на эффективность, а остальные нацелены на точность. Таким образом, более поздние (более точные) машины имели размер с плавающей запятой равным 80 битам, в то время как прежние (более эффективные / более быстрые) машины имели 64-битные двойные числа. Но это противоречило основной идее построения независимого от платформы языка. Кроме того, это может привести к потере точности / данных, когда код создается на некотором компьютере (с двойным размером 64 бита) и выполняется на другом типе компьютера (с двойным размером 80 бит).

Увеличение размера допускается, но уменьшение не допускается. Таким образом, они натолкнулись на концепцию StrongFP, то есть строгой плавающей запятой . Если вы используете это ключевое слово с классом / функцией, тогда его число с плавающей запятой и двойные числа будут иметь одинаковый размер на любой машине. т.е. 32/64 -бит соответственно.

21 голосов
/ 06 февраля 2009

Вот несколько ссылок:

  • Использование строгого пароля (Технический совет JDC)
  • jGuru: Для чего нужен модификатор strictfp? Когда я рассмотрю возможность его использования?

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

  • strictfp - Глоссарий Java

    Аппаратное обеспечение с плавающей запятой вычисляет с большей точностью и с большим диапазоном значений, чем требует спецификация Java. Было бы странно, если бы некоторые платформы давали больше точности, чем другие. Когда вы используете модификатор strictfp для метода или класса, компилятор генерирует код, который строго соответствует спецификации Java для идентичных результатов на всех платформах. Без strictfp он немного слабее, но не настолько слаб, чтобы использовать защитные биты в Pentium для обеспечения точности 80 бит.

  • И, наконец, актуальная спецификация языка Java, §15.4 Выражения строгого FP :

    В выражении строгого FP все промежуточные значения должны быть элементами набора значений с плавающей запятой или набора двойных значений, подразумевая, что результаты всех выражений строгого FP должны быть теми, которые предсказаны арифметикой IEEE 754 для операндов, представленных с использованием одиночного и двойные форматы. В выражении, которое не является строгим по FP, предоставляется некоторая свобода для реализации, чтобы использовать расширенный диапазон экспонент для представления промежуточных результатов; общий эффект, грубо говоря, состоит в том, что вычисление может дать «правильный ответ» в ситуациях, когда исключительное использование набора значений с плавающей запятой или набора двойных значений может привести к переполнению или недостаточному заполнению.

Я лично никогда не пользовался этим.

12 голосов
/ 06 февраля 2009

Как и в других упомянутых ответах, это приводит к тому, что промежуточные результаты с плавающей запятой соответствуют спецификации IEEE. В частности, процессоры x86 могут хранить промежуточные результаты с точностью, отличной от спецификации IEEE. Ситуация усложняется, когда JIT оптимизирует конкретное вычисление; порядок, в котором инструкции могут отличаться каждый раз, приводя к немного другому округлению.

Служебная нагрузка, понесенная строгим fp, вероятно, будет сильно зависеть от процессора и JIT. Эта статья в Википедии о SSE2 , похоже, дает некоторое представление о проблеме. Поэтому, если JIT может генерировать инструкции SSE для выполнения вычислений, кажется, что strictfp не будет иметь никаких накладных расходов.

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

8 голосов
/ 19 сентября 2012
  • strictfp - модификатор, который ограничивает вычисления с плавающей запятой согласно IEEE 754.

  • Это может быть использовано для всего класса, например, "public strictfp class StrictFpModifierExample {}" или для метода "public strictfp void example ()". Если он используется в классе, то все методы будут следовать IEEE 754 и если используются по методу, то конкретный метод будет следовать IEEE 754.

  • Почему это используется ?? ::: Поскольку разные платформы имеют различное аппаратное обеспечение с плавающей запятой, которое вычисляет с большей точностью и большим диапазоном значений, чем требует спецификация Java, что может давать различный выходной сигнал на различных пластинчатых формах. Таким образом, он подтверждает один и тот же выходной сигнал независимо от форм различных пластин

  • strictfp также позволяет воспользоваться преимуществами скорости и точности операций с плавающей запятой повышенной точности.

  • Нет недостатка в этом ключевом слове, которое мы можем использовать при выполнении вычислений с плавающей запятой

  • Мое последнее замечание - что такое IEEE754 вкратце IEEE 754 определяет стандартный метод как для вычислений с плавающей запятой, так и для хранения значений с плавающей запятой либо с одинарной (32-битной, используется в Java-плавающих), либо с двойной (64-битной, используется в Java-двойной) точностью. Он также определяет нормы для промежуточных вычислений и для форматов расширенной точности.

2 голосов
/ 08 июля 2015

strictfp является ключевым словом и может использоваться как модификатор без доступа для классов или методов (но не переменных). Пометка класса как strictfp означает, что любой код метода в классе будет соответствовать стандартным правилам IEEE 754 для чисел с плавающей запятой.

Без этого модификатора плавающие точки, используемые в методах, могут вести себя в зависимости от платформы. С его помощью вы можете предсказать, как ваши плавающие точки будут вести себя независимо от базовой платформы, на которой работает JVM. Недостатком является то, что если базовая платформа способна поддерживать большую точность, метод strictfp не сможет воспользоваться этим.

Если вы не объявите класс как strictfp, вы все равно можете получить поведение strictfp для каждого метода, объявив метод как strictfp.

~ SCJP Sun® Сертифицированный программатор для Java ™ 6 - Кэти Сьерра и Берт Бейтс ~

0 голосов
/ 18 августа 2018

Пример, приведенный ниже, поможет лучше понять это: В Java всякий раз, когда мы используем поиск точной информации для любой операции, например. если мы сделаем удвоение num1 = 10e + 102; двойное число2 = 8e + 10; результат = num1 + num2;

        The output will be so long and not precise, becasue it is precissed by the hardware e.g JVM and JIT has the license 
        as long as we dont have specify it Strictfp

Marking it Strictfp will make the result Uniform on every hardware and platform, because its precised value will be same
One scenario I can see is in a distributed application (or multiplayer game) where all floating-point calculations need to 
be deterministic no matter what the underlying hardware or CPU is.
...