为什么将非strictfp模式下的转换视为丢失信息的转换?

Why is the conversion in non-strictfp mode considered as the one losing information?

我理解在 strictfp 模式下的转换是为了可移植性,而不是为了 this question 中提到的准确性。但是,Java 语言规范,Java SE 8 版说

A widening primitive conversion from float to double that is not strictfp may lose information about the overall magnitude of the converted value.

在我看来,扩大原始转换 即 strictfp 旨在提高准确性。此外,我怀疑 double 可以从字面上表示 float 可以采用的所有值,其中我看不出为什么从 float 到 double 的转换在这里是一个问题。

编辑:

规范中的措辞“...可能会丢失关于...”的信息让我感觉非严格模式下的转换缺乏某种准确性与 strictfp 模式相比。这对我来说没有意义,因为非 strictfp 模式下的转换可能会使用更高精度的中间值。本题最初是基于这样的理解而写的,可能看起来并没有你想象的那么好。

Intel 的 IA64 架构使用固定的浮点寄存器格式,一个符号位,17 个指数位和 64 个有效位。当浮点数从这些寄存器之一存储到 32 位或 64 位变量时,必须对其进行转换。

Java 旨在获得一致的结果,因此不希望表达式的值根据中间结果是保存在寄存器中还是作为内存中的浮点数或双精度数而改变。

最初,Java 只是坚持要完成所有计算,就好像所有中间结果都已存储一样。由于难以在每次计算中强制指数进入正确的范围,结果证明性能不佳。解决方案是让程序员在完全一致的 strictfp 模式和更宽松的模式之间进行选择,在这种模式下,指数可以超出表达式类型的范围,而不会将值强制为零或无穷大。

假设,在宽松模式下,寄存器内浮点数的指数超出双倍指数范围,并且正在转换为内存中双精度数。该转换将强制值变为零或无穷大,从而失去其大小。这是扩大算术转换保持整体幅度的一般规则的例外。

如果在 strictfp 模式下进行相同的计算,则不允许浮点数具有超出浮点数范围的指数。无论生成什么计算,它都会将值强制为零或无穷大。每个 float 值都可以用 double 精确表示,因此转换根本不会改变值,更不用说丢失整体大小了。