275

我已经查过了它的作用,但实际上有没有人有一个例子说明你什么时候strictfp在 Java 中使用关键字?有没有人真的发现了这个的用途?

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

4

11 回答 11

286

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

从 JLS

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

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

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

于 2009-02-05T21:23:27.957 回答
67

实际上,有一篇关于 strictfp 的很好的 Wikipedia 文章,其中包含指向Java 规范中关于浮点类型、格式和值的部分的链接。

字里行间的意思是,如果您不指定strictfp,则 JVM 和 JIT 编译器有权根据需要计算您的浮点计算。为了速度,他们很可能会将计算委托给您的处理器。启用后,计算必须符合 IEEE 754 算术标准,这在strictfp实践中可能意味着 JVM 将执行计算。

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

于 2009-02-05T21:16:06.740 回答
27

一切从一个故事开始,

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

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

于 2015-07-13T21:44:41.083 回答
23

Java 17 更新

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

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


原始答案

这里有几个参考:

  • 使用 strictfp(JDC 技术提示)

  • jGuru:strictfp 修饰符有什么用?我什么时候会考虑使用它?

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

  • strictfp - Java 术语表

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

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

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

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

于 2009-02-05T21:24:33.603 回答
12

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

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

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

于 2009-02-05T21:45:58.257 回答
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) doubles) 精度。它还定义了中间计算和扩展精度格式的规范。

于 2012-09-19T19:09:14.547 回答
2

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

如果没有该修饰符,方法中使用的浮点可能会以平台相关的方式运行。有了它,您可以预测浮点的行为方式,而不管 JVM 运行在什么底层平台上。不利的一面是,如果底层平台能够支持更高的精度,strictfp则方法将无法利用它。

如果您不将类声明为strictfp,您仍然可以strictfp通过将方法声明为 来逐个方法获取行为strictfp

~ SCJP Sun®Certified Programmer for Java™ 6 - Kathy Sierra & Bert Bates ~

于 2015-07-08T11:17:28.947 回答
1

从 Java 17+ 开始,strictfp 修饰符已经过时并且什么都不做。您不应再使用此修饰符。

于 2021-12-31T23:39:10.420 回答
0

下面的示例可能有助于更清楚地理解这一点:在 java 中,每当我们使用查找任何操作的精确信息时,例如,如果我们执行 double num1 = 10e+102; 双 num2 = 8e+10 ; 结果 = 数字 1 + 数字 2;

        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.
于 2018-08-18T07:54:35.710 回答
0

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

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

参考链接

于 2019-12-23T13:00:10.600 回答
0

我需要的一次(也是唯一一次)是与 IBM ZSeries 协调。会计和大型机之外;不。已经有一段时间了,但我相当肯定大型机没有改变。

于 2022-02-18T23:55:36.887 回答