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

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

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

89675 次浏览

实际上,有一个很好的维基百科上关于strictfp的文章,带有到Java规范浮点类型、格式和值的链接。

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

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

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

来自JLS:

在fp严格表达式中,所有 中间值必须是元素 浮点值集或双精度浮点 值集,表示结果 所有FP-strict表达式的 由IEEE 754算法预测的 在使用single表示的操作数上 还有双重格式。在一个 不严格fp的表达式 留出余地 实现来使用扩展的 要表示的指数范围 中间结果;净效应, 粗略地说,那是一个 计算可能产生“正确的” 在排他的情况下回答“” 使用浮点值集或double 值设置可能导致溢出或 下溢。< / p >

换句话说,它是关于确保Write-Once-Run-Anywhere实际上意味着Write-Once-Get-Equally-Wrong-Results-Everywhere

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

Java 17更新

strictfp具有如此狭窄的用例集,以至于在Java 17中,它的功能已被删除。它仍然是一个有效的修饰符,但现在是strictfp什么都不做 (JLS源)。

相反,所有浮点运算现在都是严格的,就像在Java 1.2中引入strictfp之前一样。在现代处理器上,不再有任何额外的性能成本。


原来的答案

以下是一些参考资料:

  • 使用strictfp (JDC技术提示)

  • < p > jGuru: strictfp修饰符是干什么用的?我什么时候考虑使用它?

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

  • < p > strictfp - Java术语

    浮点硬件的计算精度更高,值的范围也比Java规范要求的更大。如果某些平台给出的精度比其他平台更高,就会令人困惑。当你在方法或类上使用strictfp修饰符时,编译器会生成严格遵守Java规范的代码,以在所有平台上获得相同的结果。没有strictfp, is稍微宽松一些,但没有宽松到在Pentium中使用守护位来提供80位精度。

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

    在FP-strict表达式中,所有中间值必须是浮点值集或double值集的元素,这意味着所有FP-strict表达式的结果必须是IEEE 754算法对使用单格式和双格式表示的操作数所预测的结果。在不严格fp的表达式中,允许实现使用扩展的指数范围来表示中间结果;粗略地说,最终的结果是计算可能会产生“正确的答案”。在独占使用浮点值集或双值集可能导致溢出或下溢的情况下。

不过我个人从来没用过它。

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

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

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

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

  • 这可以用于整个类,如“公共strictfp类StrictFpModifierExample{}”或方法“公共strictfp void example()”。如果它被用于类,那么所有方法都将遵循IEEE 754,如果它被用于方法,那么特定方法将遵循IEEE 754。

  • 为什么使用它??::: 由于不同的平台有不同的浮点硬件,计算精度更高,值的范围比java规范要求的更大,这可能会在不同的平台上产生不同的输出。因此,无论不同平台

  • ,它都确认相同的输出
  • Strictfp还确保利用扩展精度浮点操作的速度和精度。

  • 当我们进行浮点计算时,使用这个关键字没有任何缺点

  • 我的最后一点是——简而言之,什么是IEEE754 IEEE 754定义了浮点计算和浮点值的单精度(32位,用于Java浮点)或双精度(64位,用于Java双精度)存储的标准方法。

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

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

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

~ SCJP Sun®Java™6认证程序员Kathy Sierra &伯特·贝茨~

一切都始于一个故事,

当James Gosling, Herbert和他的团队开发java的时候。他们脑子里有个疯狂的东西叫< em >平台独立性< / em >。他们想让橡木(Java)变得更好,以至于它可以在任何具有不同指令集的机器上完全相同地运行,甚至运行不同的操作系统。但是,在编程语言中,小数点也被称为浮点数和双精度数有一个问题。一些机器的目标是有效的,而其他的目标是准确的。因此,后一种(更精确)机器的浮点数大小为80位,而前一种(更高效/更快)机器的浮点数大小为64位双精度。但是,这违背了我们构建独立于平台的语言的核心思想。另外,当代码在某些机器(64位的两倍大小)上构建并在另一种机器(80位的两倍大小)上运行时,这可能会导致精度/数据的损失。

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

下面的例子可能有助于更清楚地理解这一点: 在java中,当我们使用查找任何操作的精确信息时,例如。 如果我们做double num1 = 10e+102;Double num2 = 8e+10;

. Result = 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.

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

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

参考链接

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

一次(也是唯一一次)我需要这是和解与IBM ZSeries。在会计和大型机之外;不。有一段时间了,但我相当确定大型机没有改变。