我已经查了这是做什么,但有人实际上有一个例子,当你在Java中使用strictfp关键字?有人真的发现它的用处了吗?

把它放在所有浮点运算上会有什么副作用吗?


当前回答

正如其他答案所提到的,它导致中间浮点结果符合IEEE规范。特别是x86处理器可以存储与IEEE规范不同精度的中间结果。当JIT优化特定的计算时,情况变得更加复杂;指令的顺序可能每次都不同,导致舍入略有不同。

由strictfp引起的开销可能非常依赖于处理器和JIT。 这篇关于SSE2的维基百科文章似乎对这个问题有一些见解。 因此,如果JIT可以生成SSE指令来执行计算,那么strictfp似乎不会有任何开销。

在我当前的项目中,有几个地方我使用了strictfp。有一点,潜在的宇宙射线需要从像素值中去除。如果一些外部研究人员在他们面前有相同的像素值和宇宙射线,他们应该得到与我们的软件相同的结果值。

其他回答

实际上,维基百科上有一篇关于strictfp的好文章,其中有一个指向Java规范中浮点类型、格式和值部分的链接。

字里行间的意思是,如果您没有指定strictfp,那么JVM和JIT编译器就有权按它们想要的方式计算您的浮点计算。为了提高速度,它们很可能将计算委托给您的处理器。在使用strictfp时,计算必须符合IEEE 754算术标准,这在实践中可能意味着JVM将执行计算。

那么为什么要使用strictfp呢?我能看到的一个场景是在分布式应用程序(或多人游戏)中,无论底层硬件或CPU是什么,所有浮点计算都需要是确定的。代价是什么?很可能是执行时间。

正如其他答案所提到的,它导致中间浮点结果符合IEEE规范。特别是x86处理器可以存储与IEEE规范不同精度的中间结果。当JIT优化特定的计算时,情况变得更加复杂;指令的顺序可能每次都不同,导致舍入略有不同。

由strictfp引起的开销可能非常依赖于处理器和JIT。 这篇关于SSE2的维基百科文章似乎对这个问题有一些见解。 因此,如果JIT可以生成SSE指令来执行计算,那么strictfp似乎不会有任何开销。

在我当前的项目中,有几个地方我使用了strictfp。有一点,潜在的宇宙射线需要从像素值中去除。如果一些外部研究人员在他们面前有相同的像素值和宇宙射线,他们应该得到与我们的软件相同的结果值。

strictfp是一个关键字,可以用作类或方法的非非访问修饰符(但不能用作变量)。将类标记为strictfp意味着类中的任何方法代码都将符合IEEE 754浮点标准规则。

如果没有这个修饰符,方法中使用的浮点可能会以依赖于平台的方式运行。有了它,无论JVM运行在哪个底层平台上,您都可以预测浮点数的行为。缺点是,如果底层平台能够支持更高的精度,那么strictfp方法将无法利用它。

如果您没有将一个类声明为strictfp,那么通过将一个方法声明为strictfp,您仍然可以在逐个方法的基础上获得strictfp行为。

~ SCJP Sun®Java™6认证程序员- Kathy Sierra & Bert Bates ~

Strictfp确保在每个平台上从浮点计算中得到完全相同的结果。如果不使用strictfp, JVM实现可以在可用的地方使用额外的精度。

来自JLS:

Within an FP-strict expression, all intermediate values must be elements of the float value set or the double value set, implying that the results of all FP-strict expressions must be those predicted by IEEE 754 arithmetic on operands represented using single and double formats. Within an expression that is not FP-strict, some leeway is granted for an implementation to use an extended exponent range to represent intermediate results; the net effect, roughly speaking, is that a calculation might produce "the correct answer" in situations where exclusive use of the float value set or double value set might result in overflow or underflow.

换句话说,就是要确保Write-Once-Run-Anywhere实际上意味着write - once - get - equal - wrong - results - everywhere。

使用strictfp,您的结果是可移植的,没有它,它们更可能是准确的。

从Java 17+开始,strictfp修饰符已经过时,没有任何作用。你不应该再使用这个修饰符。