我查阅了这个关键字的含义,但是有人能否给一个使用Java中的 strictfp
关键字的例子?有人真的用过这个吗?
在所有我的浮点运算操作上都加上它会有什么副作用吗?
我查阅了这个关键字的含义,但是有人能否给一个使用Java中的 strictfp
关键字的例子?有人真的用过这个吗?
在所有我的浮点运算操作上都加上它会有什么副作用吗?
Strictfp确保你的浮点数计算在每个平台上都能得到完全相同的结果。如果你不使用strictfp,JVM实现可以在可用的情况下使用额外的精度。
在FP-strict表达式中,所有中间值必须是float值集或double值集的元素,这意味着所有FP-strict表达式的结果必须与使用单精度和双精度格式表示的操作数在IEEE 754算术上预测的结果相同。在不是FP-strict的表达式中,一些实现允许使用扩展指数范围来表示中间结果;粗略地说,其净效应是,在仅使用float值集或double值集可能导致溢出或下溢的情况下,计算可能产生“正确的答案”。
换句话说,这就是确保一次编写,到处运行实际上意味着一次编写,到处获得完全错误的结果。
使用strictfp可以使你的结果具有可移植性,否则可能更准确。
strictfp
计算,也会使用甚至不太理想的8087 FPU。只需稍微小心一点即可。参见 https://dev59.com/eWMl5IYBdhLWcg3wVlpf - Pascal Cuoqstrictfp
确保符合IEEE 754标准(以便在所有平台上获得相同的结果)。我唯一能看到的缺点是您可能会失去在本地硬件中拥有真正好的FPU的好处。 - typeracerstrictfp
的使用范围非常狭窄。因此,从 Java 17 开始,该功能已被删除。它仍然是一个有效的修饰符,但现在strictfp
不会执行任何操作 (JLS来源)。
相反,在 Java 1.2 引入 strictfp
之前所有浮点数操作都是严格的。在现代处理器上,不再有额外性能成本。
以下是几个参考文献:
使用 strictfp (JDC 技巧)
jGuru:什么是 strictfp 修饰符?何时应考虑使用它?
基本上,问题就在于你是否关心代码中浮点表达式的结果是快速还是可预测的。例如,如果你需要你的代码使用浮点数值计算出来的答案在多个平台上保持一致,则使用
strictfp
。
浮点硬件使用比Java规范要求更高的精度和更大的值域进行计算。如果一些平台提供比其他平台更高的精度,则会令人困惑。当你在方法或类上使用
strictfp
修饰符时,编译器生成严格遵循Java规范的代码,以在所有平台上产生相同的结果。没有strictfp
,则略微宽松,但不会使用Pentium的守卫位提供80位的精度。
最后是实际的Java语言规范,§15.4 FP-strict 表达式:
在 FP-strict 表达式中,所有中间值必须是 float 值集或 double 值集的元素,这意味着所有 FP-strict 表达式的结果必须是使用单精度和双精度格式表示的操作数在 IEEE 754 算术下预测的结果。在不是 FP-strict 的表达式中,允许实现使用扩展指数范围表示中间结果;粗略地说,这样做会使计算在只使用 float 值集或 double 值集可能导致溢出或下溢情况下产生“正确的答案”。
虽然我个人从未使用过它。
strictfp
,账本没能完全平衡。这是一个有趣的 bug,需要找到并修复它。 - Elliott Frisch这一切始于一个故事,
当詹姆斯·高斯林(James Gosling)、赫伯特和他们的团队开发Java时。他们有一个疯狂的想法,叫做平台无关性。他们想让oak(Java)变得更好,以便在任何具有不同指令集、甚至运行不同操作系统的机器上都能完全相同地运行。但是,编程语言中的十进制数(也称为浮点数和双精度)存在一个问题。有些机器着眼于效率而另一些则着眼于精确性。 因此,后者(更准确的机器)的浮点大小为80位,而前者(更有效/更快的机器)的双精度为64位。但是,这与他们构建一个平台无关的语言的核心思想相违背。此外,这可能会导致在某台机器(拥有64位双精度)上构建代码并在另一种类型的机器(拥有80位双精度)上运行时出现精度/数据丢失。
可以容忍向上扩展,但不能向下扩展。 因此,他们遇到了一个名为“strictfp”的概念,即严格浮点。如果您在一个类/函数中使用此关键字,则它的浮点数和双精度在任何机器上都具有一致的大小。即32/64位。
strictfp是一种关键字,它按照IEEE 754的规范限制浮点数计算。
可以在整个类中使用,如"public strictfp class StrictFpModifierExample{}",也可以在方法上使用,如"public strictfp void example()"。如果用于类,则所有方法都将遵循IEEE 754;如果用于方法,则特定方法将遵循IEEE 754。
为什么要使用它?因为不同平台有不同的浮点硬件,可以比Java规范要求更精确地计算更大范围的值,这可能会在不同平台上产生不同的输出,而strictfp可以确保相同的输出无论在哪个平台上运行。
使用strictfp还可以利用扩展精度浮点运算的速度和精度。
这个关键字没有任何缺点,我们在进行浮点数计算时可以使用它。
最后一个问题是-什么是IEEE 754? IEEE 754定义了标准方法,用于单精度(32位,用于Java浮点数)或双精度(64位,用于Java双精度)精度的浮点计算和浮点值的存储。它还为中间计算和扩展精度格式定义了规范。
strictfp
是一个关键字,可用作类或方法的非访问修饰符(但永远不会用于变量)。将类标记为strictfp
意味着类中的任何方法代码都将符合IEEE 754浮点规则。如果没有该修饰符,则在方法中使用的浮点数可能以平台相关的方式运行。有了它,您可以预测您的浮点数将如何运行,而不管JVM正在运行的底层平台如何。缺点是,如果底层平台能够支持更高的精度,则strictfp
方法将无法利用它。如果您未将类声明为strictfp
,仍然可以通过将方法声明为strictfp
来逐个方法地获得strictfp
行为。从Java 17+开始,strictfp修饰符已经过时并且不起作用。您不再需要使用此修饰符。
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' 关键字用于强制浮点计算(float 或 double)在 Java 中符合 IEEE 的 754 标准,显式地。如果您不使用 strictfp 关键字,则浮点精度取决于目标平台的硬件。
如果一个接口或类被声明为 strictfp,则该接口或类中的所有方法和嵌套类型都隐式地是 strictfp。
参考 link