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


258

我已经查看了它的功能,但是实际上没有人举一个例子说明何时strictfp在Java中使用关键字吗?有人真的为此找到了用处吗?

仅将其放在我所有的浮点运算中会有副作用吗?


1
始终如此,除非您实际需要的性能超过了可重复性。
锑2012年

1
@锑-或精度/正确性。例如,x86 / x64在内部使用80位浮点寄存器,因此对于长时间的计算,如果没有strictfp,结果将更加准确。
罗伯特·弗雷泽

1
@Robert实际上,该规范保证了尾数的有限精度。唯一的区别是它可以使用比正常值大的指数精度,这在极少数情况下由于两次舍入而具有差异。

我认为,除了可以在关节周围撒上这个有用的修饰符之外,新的sfloat和sdouble原始strictfp数据类型可能是一个好主意。
theRiley

Answers:


274

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

从JLS

在FP-strict表达式中,所有中间值都必须是浮点值集或double值集的元素,这意味着所有FP-strict表达式的结果必须是IEEE 754算法对使用单格式和双格式表示的操作数预测的结果。在不受FP限制的表达式中,为实现提供了一定的回旋余地,可以使用扩展的指数范围来表示中间结果。粗略地说,最终结果是,在独占使用浮点值集或双精度值集可能导致上溢或下溢的情况下,计算可能会产生“正确答案”。

换句话说,这是要确保Write-Once-Run-Anywhere实际上意味着Write-Once-Get-Equally-错误结果-Everywhere

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


28
将其用于可重复的科学结果和精确的单位测试。
Aleksandr Dubinsky 2014年

1
“如果使用strictfp,那么JVM实现可以自由使用额外的精度(如果可用)”,这听起来像是一件坏事:P
AMDG,

@LinkTheProgrammer它当然可以是一件坏事
蒂姆

@TimCastelijns我想是《欢乐车轮》的参考吗?重播记录击键;由于FP-math实现的精度差异,因此重放仅在类似硬件上才是准确的。您能说出一个由浮点数学可变性引起的更现实的问题吗?我可以想象一个粒子模拟器,但是还有什么呢?
AMDG

因此,这意味着我们应该始终在涉及多个平台的生产中使用strictfp?
Beatrice

65

维基百科实际上有关于这个话题的好文章在这里,并链接到Java规范。

在各行之间阅读时,意味着如果您未指定strictfp,那么JVM和JIT编译器将获得许可,可根据需要进行浮点计算。为了提高速度,他们很可能会将计算委托给您的处理器。随着strictfp上的计算必须符合IEEE 754算法标准,在实践中,可能意味着JVM会做计算。

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


5
“扩展的指数范围来表示中间结果”不是“按需计算浮点计算的许可证”,实际上,即使是strictfp计算,也使用了无用的8087 FPU。只有在这种情况下,才需要稍加注意。见stackoverflow.com/questions/18496560/...
帕斯卡尔Cuoq

我同意@PascalCuoq re的意见:“可以根据需要获得许可来计算浮点计算”。如果有的话,在这种情况下,相反的情况似乎是正确的,因为可以strictfp确保符合IEEE 754标准(以便在所有平台上获得相同的结果)。我能看到的唯一缺点是,您可能会失去在本地硬件中拥有非常好的FPU的好处。
typeracer

25

一切始于一个故事,

James Gosling,Herbert和他的团队的其他成员开发Java时。他们想到了这种疯狂的东西,称为平台独立性。他们想做橡木(Java)更好,它可以在具有不同指令集的任何机器上运行完全相同,甚至可以运行不同的操作系统。但是,在编程语言中,小数点编号(也称为浮点数和双精度数)存在问题。有些机器的目标是提高效率,而其他机器的目标是精度。因此,较新的(更准确的)计算机浮点数为80位,而较旧的(更有效/更快)的计算机则浮点数为64位。但是,这与构建平台独立语言的核心思想背道而驰。同样,当代码在某些机器上构建(具有64位大小的两倍)并在另一种机器上运行(具有80位大小的两倍)时,这可能会导致精度/数据丢失。

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


8
strictfp是Java 1.2中引入的。这比设计橡木时要晚得多。
托尔比约恩Ravn的安徒生

“小数点编号也称为浮点数”-十进制表示以10为底的数字,与浮点表示形式无关。
aioobe '19

21

以下是一些参考:

  • 使用strictfp(JDC技术提示)
  • jGuru:strictfp修饰符是做什么用的?我什么时候考虑使用它?

    基本上,所有这些归结为您是否在乎代码中浮点表达式的结果是快速还是可预测的。例如,如果您需要代码附带的答案,该答案使用浮点值在多个平台上保持一致,则可以使用strictfp

  • strictfp-Java词汇表

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

  • 最后是实际的Java语言规范§15.4FP-strict表达式

    在FP-strict表达式中,所有中间值都必须是浮点值集或double值集的元素,这意味着所有FP-strict表达式的结果必须是IEEE 754算法对使用单格式和双格式表示的操作数预测的结果。在不受FP限制的表达式中,为实现提供了一定的回旋余地,可以使用扩展的指数范围来表示中间结果。粗略地说,最终结果是,在独占使用浮点值集或双精度值集可能导致上溢或下溢的情况下,计算可能会产生“正确答案”。

不过,我个人从未使用过它。


12

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

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

在我当前的项目中,有一些地方使用strictfp。有一点需要将潜在的宇宙射线从像素值中删除。如果某些外部研究人员在其前面具有相同的像素值和宇宙射线,则它们应获得与我们的软件相同的结果值。


8
  • strictfp是一个修改器,它根据IEEE 754限制浮点计算。

  • 可以在整个类(例如“ public strictfp类StrictFpModifierExample {}”)上使用,也可以在方法“ public strictfp void example()”上使用。如果在类上使用,则所有方法都将遵循IEEE 754;如果在方法上使用,则将使用特定方法遵循IEEE 754。

  • 为什么使用它??平台

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

  • 在进行浮点计算时,可以使用此关键字没有缺点

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


2

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

如果没有该修饰符,则方法中使用的浮点可能会以依赖于平台的方式运行。有了它,您可以预测浮点将如何运行,而与运行JVM的基础平台无关。缺点是,如果基础平台能够支持更高的精度,则某种strictfp方法将无法利用它。

如果不将类声明为strictfp,则仍然可以strictfp通过将方法声明为来获得基于方法的行为strictfp

〜SCJPSun®认证的Java™6编程器-Kathy Sierra和Bert Bates〜


0

下面的示例可能有助于更清楚地理解这一点:在Java中,无论何时我们使用任何操作寻找精确信息,例如,如果我们执行double 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.

0

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

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

参考链接

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.