Когда я должен использовать ключевое слово "strictfp" в Java?
Я посмотрел, что это делает, но есть ли у кого-нибудь пример, когда вы будете использовать strictfp
ключевое слово в Java? Кто-нибудь на самом деле нашел применение для этого?
Будут ли какие-либо побочные эффекты от того, что я просто добавлю это на все мои операции с плавающей запятой?
11 ответов
Strictfp гарантирует, что вы получите точно такие же результаты от ваших вычислений с плавающей запятой на каждой платформе. Если вы не используете strictfp, реализация JVM может использовать дополнительную точность там, где это возможно.
В выражении строгого FP все промежуточные значения должны быть элементами набора значений с плавающей запятой или набора двойных значений, подразумевая, что результаты всех выражений строгого FP должны быть теми, которые предсказаны арифметикой IEEE 754 для операндов, представленных с использованием одинарного и двойного форматов., В выражении, которое не является строгим по FP, предоставляется некоторая свобода для реализации, чтобы использовать расширенный диапазон показателей для представления промежуточных результатов; общий эффект, грубо говоря, заключается в том, что вычисление может дать "правильный ответ" в ситуациях, когда исключительное использование набора значений с плавающей запятой или набора двойных значений может привести к переполнению или недостаточному заполнению.
Другими словами, речь идет о том, чтобы удостовериться в том, что Write-Once-Run-Anywhere на самом деле означает " Write-Once-Get-Equally-Wrong-Results-Everywhere".
Благодаря строгому результату ваши результаты переносимы, без него они, скорее всего, будут точными.
В Википедии есть хорошая статья на эту тему со ссылкой на спецификацию Java.
Чтение между строк означает, что если вы не укажете strictfp
затем JVM и JIT-компилятор имеют лицензию для вычисления ваших вычислений с плавающей запятой, как они захотят. В интересах скорости они, скорее всего, делегируют вычисления вашему процессору. С strictfp
далее, вычисления должны соответствовать арифметическим стандартам IEEE 754, что на практике, вероятно, означает, что JVM выполнит вычисления.
Так почему вы хотите использовать strictfp
? Один сценарий, который я вижу, - это распределенное приложение (или многопользовательская игра), где все вычисления с плавающей точкой должны быть детерминированными, независимо от того, какое аппаратное обеспечение или процессор используется. Какой компромисс? Скорее всего, время выполнения.
Вот несколько ссылок:
- Использование strictfp (JDC Tech Tip)
jGuru: Для чего нужен модификатор strictfp ? Когда я рассмотрю возможность его использования?
По сути, все сводится к тому, заботитесь ли вы о том, что результаты выражений с плавающей точкой в вашем коде быстрые или предсказуемые. Например, если вам нужны ответы, которые предлагает ваш код, в которых используются значения с плавающей запятой для согласованности между несколькими платформами, используйте
strictfp
,Аппаратное обеспечение с плавающей запятой вычисляет с большей точностью и с большим диапазоном значений, чем требует спецификация Java. Было бы странно, если бы некоторые платформы давали больше точности, чем другие. Когда вы используете
strictfp
модификатор метода или класса, компилятор генерирует код, который строго придерживается спецификации Java для идентичных результатов на всех платформах. Безstrictfp
Он немного слабее, но не настолько слаб, чтобы использовать защитные биты в Pentium для обеспечения точности 80 бит.И, наконец, актуальная спецификация языка Java, §15.4 Выражения строгого FP:
В выражении строгого FP все промежуточные значения должны быть элементами набора значений с плавающей запятой или набора двойных значений, подразумевая, что результаты всех выражений строгого FP должны быть теми, которые предсказаны арифметикой IEEE 754 для операндов, представленных с использованием одинарного и двойного форматов., В выражении, которое не является строгим по FP, предоставляется некоторая свобода для реализации, чтобы использовать расширенный диапазон показателей для представления промежуточных результатов; общий эффект, грубо говоря, заключается в том, что вычисление может дать "правильный ответ" в ситуациях, когда исключительное использование набора значений с плавающей запятой или набора двойных значений может привести к переполнению или недостаточному заполнению.
Впрочем, лично я никогда не пользовался этим.
Все началось с истории,
Когда java разрабатывался Джеймсом Гослингом, Гербертом и остальной его командой. Они имели в виду эту сумасшедшую вещь под названием независимость от платформы. Они хотели сделать oak(Java) настолько лучше, что он будет работать точно так же на любой машине с другим набором команд, даже с разными операционными системами. Но возникла проблема с десятичными числами, также известными как языки с плавающей запятой и double в языках программирования. Некоторые машины были построены нацелены на эффективность, а остальные нацелены на точность. Таким образом, более поздние (более точные) машины имели размер с плавающей запятой равным 80 битам, тогда как прежние (более эффективные / более быстрые) машины имели 64-битные двойные числа. Но это противоречило основной идее построения независимого от платформы языка. Кроме того, это может привести к потере точности / данных, когда код создается на некотором компьютере (с двойным размером 64 бита) и выполняется на другом типе компьютера (с двойным размером 80 бит).
Увеличение размера можно допустить, но уменьшение не может быть. Таким образом, они столкнулись с понятием строгого, то есть строгого с плавающей точкой. Если вы используете это ключевое слово с классом / функцией, то его число с плавающей запятой и двойные числа имеют одинаковый размер на любой машине. т.е. 32/64 -бит соответственно.
Как уже упоминалось в других ответах, это приводит к тому, что промежуточные результаты с плавающей запятой соответствуют спецификации IEEE. В частности, процессоры x86 могут хранить промежуточные результаты с точностью, отличной от спецификации IEEE. Ситуация усложняется, когда JIT оптимизирует конкретное вычисление; Порядок следования инструкций может отличаться каждый раз, что приводит к немного другому округлению.
Накладные расходы, понесенные строгим fp, вероятно, будут сильно зависеть от процессора и JIT. Эта статья в Википедии о SSE2, похоже, дает представление о проблеме. Поэтому, если JIT может генерировать инструкции SSE для выполнения вычислений, кажется, что strictfp не будет иметь никаких накладных расходов.
В моем текущем проекте есть несколько мест, где я использую строгий fp. Есть точка, где потенциальные космические лучи должны быть удалены из значений пикселей. Если какой-то сторонний исследователь имеет такое же значение пикселей и космический луч перед ними, они должны получить то же результирующее значение, что и наше программное обеспечение.
strictfp - это модификатор, который ограничивает вычисления с плавающей запятой согласно IEEE 754.
Это можно использовать для всего класса, например, "public StrictFP class StrictFpModifierExample{}" или для метода "public StrongFP void example()". Если он используется в классе, то все методы будут следовать IEEE 754, а если используется в методе, то конкретный метод будет следуйте IEEE 754.
Почему он используется??::: Поскольку разные платформы имеют различное аппаратное обеспечение с плавающей запятой, которое вычисляет с большей точностью и большим диапазоном значений, чем требует спецификация Java, что может давать различный вывод на различных пластинчатых формах. Таким образом, он подтверждает один и тот же вывод независимо от различий plateforms
Stringfp также обеспечивает преимущество в скорости и точности операций с плавающей запятой повышенной точности.
С этим ключевым словом нет недостатка, который мы можем использовать, когда выполняем вычисления с плавающей запятой.
Последнее, что я хочу сказать - это IEEE754, короче говоря, IEEE 754 определяет стандартный метод как для вычислений с плавающей запятой, так и для хранения значений с плавающей запятой либо в одном (32-битный, используется в Java-плавающих), или в двойном (64-битный, используется в Java) doubles) точность. Он также определяет нормы для промежуточных вычислений и для форматов с расширенной точностью.
Начиная с Java 17+ модификатор strictfp устарел и ничего не делает. Вы больше не должны использовать этот модификатор.
strictfp
является ключевым словом и может использоваться как модификатор без доступа к классам или методам (но не переменным). Отметить класс как strictfp
означает, что любой код метода в классе будет соответствовать стандартным правилам IEEE 754 для чисел с плавающей запятой.
Без этого модификатора плавающие точки, используемые в методах, могут вести себя в зависимости от платформы. С его помощью вы можете предсказать, как ваши плавающие точки будут вести себя независимо от базовой платформы, на которой работает JVM. Недостатком является то, что если базовая платформа способна поддерживать большую точность, strictfp
метод не сможет воспользоваться этим.
Если вы не объявите класс как strictfp
, вы все еще можете получить strictfp
поведение на основе метода, объявив метод как strictfp
,
~ SCJP Sun® Сертифицированный программатор для Java™ 6 - Кэти Сьерра и Берт Бейтс ~
Единственный (и единственный раз), когда мне это было нужно, — это согласование с IBM ZSeries. Вне бухгалтерского учета и мэйнфреймов; нет. Это было когда-то, но я совершенно уверен, что мэйнфреймы не изменились.
Ключевое слово strictfp используется для обеспечения точного соответствия точности вычислений с плавающей запятой (float или double) в Java стандарту IEEE 754, явным образом. Если вы не используете ключевое слово strictfp, точность с плавающей запятой зависит от оборудования целевой платформы.
Если интерфейс или класс объявлены с помощью strictfp, то все методы и вложенные типы в этом интерфейсе или классе неявно являются strictfp.
Ссылка на ссылку
Пример ниже может помочь в понимании этого более ясно: в Java всякий раз, когда мы используем поиск точной информации для любой операции, например, если мы делаем double 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.