我已经查看了它的功能,但是实际上没有人举一个例子说明何时strictfp
在Java中使用关键字吗?有人真的为此找到了用处吗?
仅将其放在我所有的浮点运算中会有副作用吗?
我已经查看了它的功能,但是实际上没有人举一个例子说明何时strictfp
在Java中使用关键字吗?有人真的为此找到了用处吗?
仅将其放在我所有的浮点运算中会有副作用吗?
Answers:
Strictfp确保您从每个平台上的浮点计算中获得完全相同的结果。如果您不使用strictfp,那么JVM实现可以自由使用,以在可用时使用额外的精度。
从JLS:
在FP-strict表达式中,所有中间值都必须是浮点值集或double值集的元素,这意味着所有FP-strict表达式的结果必须是IEEE 754算法对使用单格式和双格式表示的操作数预测的结果。在不受FP限制的表达式中,为实现提供了一定的回旋余地,可以使用扩展的指数范围来表示中间结果。粗略地说,最终结果是,在独占使用浮点值集或双精度值集可能导致上溢或下溢的情况下,计算可能会产生“正确答案”。
换句话说,这是要确保Write-Once-Run-Anywhere实际上意味着Write-Once-Get-Equally-错误结果-Everywhere。
使用strictfp,您的结果是可移植的,没有它,它们将更可能是准确的。
维基百科实际上有关于这个话题的好文章在这里,并链接到Java规范。
在各行之间阅读时,意味着如果您未指定strictfp
,那么JVM和JIT编译器将获得许可,可根据需要进行浮点计算。为了提高速度,他们很可能会将计算委托给您的处理器。随着strictfp
上的计算必须符合IEEE 754算法标准,在实践中,可能意味着JVM会做计算。
那为什么要使用strictfp
呢?我看到的一个场景是在分布式应用程序(或多人游戏)中,无论底层硬件或CPU是什么,所有浮点计算都需要确定性。有什么权衡?最可能的执行时间。
strictfp
计算,也使用了无用的8087 FPU。只有在这种情况下,才需要稍加注意。见stackoverflow.com/questions/18496560/...
strictfp
确保符合IEEE 754标准(以便在所有平台上获得相同的结果)。我能看到的唯一缺点是,您可能会失去在本地硬件中拥有非常好的FPU的好处。
一切始于一个故事,
James Gosling,Herbert和他的团队的其他成员开发Java时。他们想到了这种疯狂的东西,称为平台独立性。他们想做橡木(Java)更好,它可以在具有不同指令集的任何机器上运行完全相同,甚至可以运行不同的操作系统。但是,在编程语言中,小数点编号(也称为浮点数和双精度数)存在问题。有些机器的目标是提高效率,而其他机器的目标是精度。因此,较新的(更准确的)计算机浮点数为80位,而较旧的(更有效/更快)的计算机则浮点数为64位。但是,这与构建平台独立语言的核心思想背道而驰。同样,当代码在某些机器上构建(具有64位大小的两倍)并在另一种机器上运行(具有80位大小的两倍)时,这可能会导致精度/数据丢失。
可以容忍上调大小,但不能容忍下调大小。因此,他们遇到了strictfp的概念,即严格的浮点数。如果将此关键字与类/函数一起使用,则其浮点数和双精度数在任何计算机上的大小均一致。即分别为32/64位。
以下是一些参考:
jGuru:strictfp修饰符是做什么用的?我什么时候考虑使用它?
基本上,所有这些归结为您是否在乎代码中浮点表达式的结果是快速还是可预测的。例如,如果您需要代码附带的答案,该答案使用浮点值在多个平台上保持一致,则可以使用
strictfp
。
浮点硬件的计算比Java规范要求的精度更高,并且值的范围更大。如果某些平台比其他平台提供更高的精度,那将会令人困惑。在
strictfp
方法或类上使用修饰符时,编译器会生成严格遵循Java规范的代码,以在所有平台上获得相同的结果。如果不使用strictfp
,它会稍微松懈,但不会那么松懈,以致于无法使用Pentium中的保护位来提供80位的精度。
最后是实际的Java语言规范§15.4FP-strict表达式:
在FP-strict表达式中,所有中间值都必须是浮点值集或double值集的元素,这意味着所有FP-strict表达式的结果必须是IEEE 754算法对使用单格式和双格式表示的操作数预测的结果。在不受FP限制的表达式中,为实现提供了一定的回旋余地,可以使用扩展的指数范围来表示中间结果。粗略地说,最终结果是,在独占使用浮点值集或双精度值集可能导致上溢或下溢的情况下,计算可能会产生“正确答案”。
不过,我个人从未使用过它。
正如提到的其他答案一样,它导致中间浮点结果符合IEEE规范。特别是x86处理器可以以与IEEE规范不同的精度存储中间结果。当JIT优化特定的计算时,情况变得更加复杂。每次指令的顺序可能会有所不同,导致舍入略有不同。
strictfp产生的开销可能非常依赖处理器和JIT。这篇关于SSE2的维基百科文章似乎对此问题有一定的了解。因此,如果JIT可以生成SSE指令来执行计算,那么strictfp似乎将没有任何开销。
在我当前的项目中,有一些地方使用strictfp。有一点需要将潜在的宇宙射线从像素值中删除。如果某些外部研究人员在其前面具有相同的像素值和宇宙射线,则它们应获得与我们的软件相同的结果值。
strictfp是一个修改器,它根据IEEE 754限制浮点计算。
可以在整个类(例如“ public strictfp类StrictFpModifierExample {}”)上使用,也可以在方法“ public strictfp void example()”上使用。如果在类上使用,则所有方法都将遵循IEEE 754;如果在方法上使用,则将使用特定方法遵循IEEE 754。
为什么使用它??平台
strictfp还确保利用扩展精度浮点运算的速度和精度。
在进行浮点计算时,可以使用此关键字没有缺点
我的最后一点是-什么是IEEE754简而言之IEEE 754为浮点计算和浮点值存储(以Java浮点数使用的32位或Java用64位浮点值的标准方法)定义了标准方法精度),它还定义了用于中间计算和扩展精度格式的规范。
strictfp
是关键字,可以用作类或方法的非非访问修饰符(但不能用作变量)。将类标记为strictfp
表示该类中的任何方法代码都将符合IEEE 754标准的浮点规则。
如果没有该修饰符,则方法中使用的浮点可能会以依赖于平台的方式运行。有了它,您可以预测浮点将如何运行,而与运行JVM的基础平台无关。缺点是,如果基础平台能够支持更高的精度,则某种strictfp
方法将无法利用它。
如果不将类声明为strictfp
,则仍然可以strictfp
通过将方法声明为来获得基于方法的行为strictfp
。
〜SCJPSun®认证的Java™6编程器-Kathy Sierra和Bert Bates〜
下面的示例可能有助于更清楚地理解这一点:在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.