我什么时候应该在java中使用“strictfp”关键字?

时间:2009-02-05 21:08:34

标签: java floating-point strictfp

我已经查明了它的作用,但是有没有人真的有一个例子,说明何时在Java中使用strictfp关键字?有没有人真的找到了这个用途?

将它放在我的所有浮点运算上是否会产生任何副作用?

9 个答案:

答案 0 :(得分:258)

Strictfp可确保您在每个平台上获得与浮点计算完全相同的结果。如果不使用strictfp,JVM实现可以在可用的情况下自由使用额外的精度。

From the JLS

  

在FP-strict表达式中,全部   中间值必须是元素   float值设置或double   价值集,暗示结果   必须是所有FP严格表达式   IEEE 754算法预测的那些   在使用单个表示的操作数上   和双格式。在一个   一些不是FP严格的表达式   余地被授予   实现使用扩展   要表示的指数范围   中间结果;净效应,   粗略地说,是一个   计算可能会产生“正确的   回答“在独家的情况下   使用浮点值设置或双精度   值集可能导致溢出或   下溢。

换句话说,它是关于确保 Write-Once-Run-Anywhere 实际上意味着 Write-Once-Get-Equally-Werong-Results-Everywhere 。< / p>

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

答案 1 :(得分:60)

Wikipedia实际上有一篇关于这个主题here的好文章,附有Java规范的链接。

在行之间进行读取,这意味着如果您未指定strictfp,则JVM和JIT编译器可以根据需要计算浮点计算的许可。为了速度,他们很可能会将计算委托给您的处理器。在strictfp打开的情况下,计算必须符合IEEE 754算术标准,实际上,这可能意味着JVM将进行计算。

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

答案 2 :(得分:22)

这一切都始于一个故事,

当James由James Gosling,Herbert和他的团队的其他成员开发时。他们把这个疯狂的东西称为 平台独立性 。他们希望使 oak(Java)更好,以至于在具有不同指令集的任何机器上运行完全相同,甚至运行不同的操作系统。但是,在编程语言中,小数点数也存在问题,也称为浮点数和双精度数。一些机器的目标是效率,而休息的目标是准确性。因此,后来的(更准确的)机器的浮点大小为80位,而前者(更有效/更快)的机器有64位双倍。但是,这是建立一种独立于平台的语言的核心理念。此外,当代码在某台机器上构建(具有64位大小的两倍)并在另一种机器(具有80位大小的两倍)上运行时,这可能会导致精度/数据丢失。

可以容忍Up-Sizing,但不能使用Down-Sizing。 因此,他们遇到了strictfp的概念,即严格浮点。如果将此关键字与类/函数一起使用,则其浮点和双精度在任何计算机上都具有一致的大小。即分别为32/64位。

答案 3 :(得分:21)

以下是几个参考文献:

  • Using strictfp(JDC Tech Tip)
  • jGuru:What is the strictfp modifier for? When would I consider using it?

      

    基本上,这一切归结为您是否关心代码中的浮点表达式的结果是快速还是可预测的。例如,如果您需要使用您的代码提供的答案,并使用浮点值在多个平台上保持一致,那么请使用strictfp

  • strictfp - Java Glossary

      

    浮点硬件计算的精度更高,并且具有比Java规范要求的更大范围的值。如果某些平台比其他平台更精确,那将会令人困惑。在方法或类上使用strictfp修饰符时,编译器会生成严格遵守Java规范的代码,以便在所有平台上获得相同的结果。如果没有strictfp,它是否稍微宽松一点,但不要太宽松,以至于使用Pentium中的保护位来提供80位精度。

  • 最后是实际的Java语言规范,§15.4 FP-strict Expressions

      

    在FP-strict表达式中,所有中间值必须是浮点值集或双值集的元素,这意味着所有FP严格表达式的结果必须是IEEE 754算法在使用单个表示的操作数上预测的结果和双格式。在不是FP-strict的表达式中,为实现授予了一些余地,以使用扩展指数范围来表示中间结果;粗略地说,净效应是在独占使用浮点值集或双值集可能导致上溢或下溢的情况下,计算可能会产生“正确答案”。

但是,我从来没有亲自使用它。

答案 4 :(得分:12)

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

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

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

答案 5 :(得分:8)

  • strictfp是一个修饰符,它根据IEEE 754限制浮点计算。

  • 这可以在整个类上使用,例如“public strictfp class StrictFpModifierExample {}”或方法“public strictfp void example()”。如果它在类上使用,则所有方法都将遵循IEEE 754并且如果使用在方法上然后特定的方法将遵循IEEE 754.

  • 为什么使用?? ::: 由于不同的平台具有不同的浮点硬件,其计算的精度和范围都比java规范要求的更高,并且可能在不同的平板上产生不同的输出。因此无论不同的平板形式如何都能确认相同的输出

  • strictfp还可以确保利用扩展精度浮点运算的速度和精度。

  • 我们在进行浮点计算时可以使用这个关键字没有缺点

  • 我的最后一点是 - 简称IEEE754 IEEE 754定义了浮点计算和浮点值存储的标准方法,单个(32位,用于Java浮点数)或双精度(64位,用于Java双精度)精度。它还定义了中间计算的规范以及扩展的精确格式。

答案 6 :(得分:2)

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

如果没有该修饰符,方法中使用的浮点可能会以平台相关的方式运行。有了它,您可以预测浮点的行为,无论JVM运行的底层平台如何。缺点是如果底层平台能够支持更高的精度,strictfp方法将无法利用它。

如果您未将某个类声明为strictfp,则仍然可以通过将方法声明为strictfp来逐个方法地获得strictfp行为。

~SCCJSun®认证程序员Java™6 - Kathy Sierra&amp;伯特贝茨〜

答案 7 :(得分:0)

下面的示例可以帮助您更清楚地理解这一点: 在Java中,无论何时我们都在使用任何操作的精确信息,例如             如果我们加倍num1 = 10e + 102; double num2 = 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.

答案 8 :(得分:0)

'strictfp'关键字用于强制Java中的浮点计算(浮点或双精度)的精度明确地符合IEEE 754标准。如果您不使用strictfp关键字,则浮点精度取决于目标平台的硬件。

如果使用strictfp声明了接口或类,则该接口或类中的所有方法和嵌套类型都是隐式strictfp。

引用link