什么时候应该在java中使用“strictfp”关键字?
我已经查过这是什么,但是有没有人真的有一个例子,当你在Java中使用strictfp
关键字? 有没有人真的find了这个用途?
是否将所有的浮点操作都放在了一个副作用上?
Strictfp确保在每个平台上获得与您的浮点计算完全相同的结果。 如果您不使用strictfp,则JVM实现可以在可用的情况下自由使用额外的精度。
从JLS :
在FP-strictexpression式中,所有中间值必须是float值集或double值集的元素,这意味着所有FP-strictexpression式的结果必须是由IEEE 754algorithm对使用单格式和双格式表示的操作数所预测的结果。 在一个不是FP严格的expression式中,为了使用扩展的指数范围来表示中间结果,实现了一些余地。 总的来说,净效应是在独占使用float值集或double值集可能导致溢出或下溢的情况下,计算可能产生“正确答案”。
换句话说,就是确保Write-Once-Run-Anywhere实际上意味着Write-Once-Get-Equally-Wrong-Results-Everywhere 。
用strictfp你的结果是可移植的,没有它,他们更可能是准确的。
维基百科在这里实际上有一篇关于这个话题的好文章,并且链接到了Java规范。
在各行之间读取,其含义是,如果不指定strictfp
,则JVM和JIT编译器具有许可证,可以根据需要计算您的浮点计算。 为了提高速度,他们很可能将计算委托给处理器。 strictfp
,计算必须符合IEEE 754算术标准,实际上,这可能意味着JVM将执行计算。
那么你为什么要使用strictfp
? 我可以看到的一个场景是在分布式应用程序(或多人游戏)中,无论基础硬件或CPU是什么,所有浮点计算都需要确定性。 什么是权衡? 最有可能的执行时间。
这里有几个参考文献:
- 使用strictfp (JDC技术提示)
-
jGuru: 什么是strictfp修饰符? 我什么时候会考虑使用它?
基本上,归结起来就是你是否在乎代码中浮点expression式的结果是快速还是可预测的。 例如,如果您需要使用浮点值在多个平台间保持一致的代码,请使用
strictfp
。 -
strictfp – Java术语表
浮点硬件的计算精度更高,并且具有比Java规范要求更大的值范围。 如果一些平台比其他平台更精确,那将是令人困惑的。 在方法或类上使用
strictfp
修饰符时,编译器将生成严格遵守Java规范的代码,以在所有平台上获得相同的结果。 如果没有strictfp
,是不是稍微宽松一点,但是不要使用Pentium中的保护位来提供80位的精度。 -
最后是实际的Java语言规范,第15.4节FP-strictexpression式 :
在FP-strictexpression式中,所有中间值必须是float值集或double值集的元素,这意味着所有FP-strictexpression式的结果必须是由IEEE 754algorithm对使用单格式和双格式表示的操作数所预测的结果。 在一个不是FP严格的expression式中,为了使用扩展的指数范围来表示中间结果,实现了一些余地。 总的来说,净效应是在独占使用float值集或double值集可能导致溢出或下溢的情况下,计算可能产生“正确答案”。
不过,我从来没有亲自使用它。
这一切都始于一个故事,
当Java由James Gosling,Herbert和他的其他团队开发的时候。 他们有这个疯狂的东西在脑海里被称为平台独立 。 他们希望使橡木(Java)变得更好,以至于在任何具有不同指令集的机器上运行完全相同,甚至运行不同的操作系统。 但是,在编程语言中,小数点数也被称为浮点和双精度。 有些机器是以效率为目标,其余的则以精确度为目标。 所以,后来的(更精确的)机器的浮点大小为80位,而前者(更高效/更快)的机器有64位双倍。 但是,这与构build独立于平台的语言的核心思想是不一致的。 另外,当一些代码是在一些机器(具有64位大小的双倍)并且在另一种机器(具有80位大小的双倍)上运行时,这可能导致精度/数据的丢失。
上调可以容忍,但是下调不能。 于是,他们遇到了strictfp即严格浮点的概念。 如果你在一个类/函数中使用这个关键字,那么它的浮点和双精度在任何机器上都是一致的。 即分别为32/64位。
正如上面提到的其他答案,它会导致中间浮点结果符合IEEE规范。 特别是x86处理器可以按照IEEE规范以不同的精度存储中间结果。 当JIT优化一个特定的计算时,情况变得更加复杂; 指令的顺序可能会不同,每次导致稍微不同的舍入。
strictfp产生的开销很可能是处理器和JIT的依赖。 这篇关于SSE2的维基百科文章似乎对这个问题有一定的了解。 所以如果JIT可以生成SSE指令来执行计算,那么strictfp似乎不会有任何开销。
在我目前的项目中,有一些地方使用strictfp。 有一点需要从像素值中去除潜在的宇宙射线。 如果一些外部研究人员在他们面前具有相同的像素值和宇宙射线,他们应该得到与我们的软件相同的结果值。
-
strictfp是一个限制按照IEEE 754进行浮点计算的修饰符。
-
这可以用于整个类,比如“public strictfp class StrictFpModifierExample {}”或方法“public strictfp void example()”。如果在类上使用,那么所有的方法都遵循IEEE 754,如果在方法上使用,那么特定的方法遵循IEEE 754。
-
为什么使用?:::因为不同的平台有不同的浮点硬件,这些硬件的计算精度更高,值的范围也比java规范要求的要高,可能会在不同的平台上产生不同的输出,所以它确认了相同的输出, plateforms
-
strictfp还可以确保利用扩展精度浮点运算的速度和精度。
-
当我们正在做浮点计算时,我们可以使用这个关键字没有缺点
-
我的最后一点是:什么是IEEE754总之,IEEE 754定义了浮点计算和存储浮点值的标准方法,无论是单个(32位,用在Java浮点数)还是双精度(64位,用在Java双精度)。它还定义了中间计算和扩展精度格式的规范。
strictfp
是一个关键字,可以用作类或方法的非非访问修饰符(但永远不会variables)。 将类标记为strictfp
意味着类中的任何方法代码都将符合IEEE 754浮点标准规则。
如果没有这个修饰符,方法中使用的浮点可能会依赖于平台。 有了它,您就可以预测浮点的行为如何,而不pipeJVM运行的底层平台如何。 缺点是如果底层平台能够支持更高的精度, strictfp
方法将无法利用它。
如果您没有将类声明为strictfp
,那么您仍然可以通过将方法声明为strictfp
逐个方法地获取strictfp
行为。
〜SCJPSun®Java™6authentication程序员 – Kathy Sierra&Bert Bates〜