在 Java 中从双精度转换为浮点型

如果我正在使用 一个 ,并且我将其转换为 ,这是如何工作的?该值是否会被截断,以便它适合浮点数?还是值的舍入方式不同?抱歉,如果这听起来有点补救,但我试图掌握和转换的概念。doublefloatfloatdouble


答案 1

来自 Java 语言规范的第 5.1.3 节

从双精度到浮点数的缩小基元转换受 IEEE 754 舍入规则 (§4.2.4) 的约束。这种转换可能会失去精度,但也会失去范围,导致非零双精度值的浮点数零和有限双精度值的浮点数无穷大。双 NaN 转换为浮点数 NaN,双无穷大转换为同符号浮点数无穷大。

第4.2.4节说:

Java 编程语言要求浮点算术的行为就像每个浮点运算符都将其浮点结果舍入为结果精度一样。不精确的结果必须四舍五入到最接近无限精确结果的可表示值;如果两个最接近的可表示值相等接近,则选择其最低有效位为零的值。这是 IEEE 754 标准的默认舍入模式,称为舍入到最接近。


答案 2

我建议将浮点类型视为最有用的表示值的范围。0.1f显示为0.1而不是0.100000001490116119384765625的原因是它实际上代表了从13421772.5/134217728到13421773.5/134217728的数字范围(即从0.0999999977648258209228515625到0.1000000052154064178466796875);添加额外的数字来指示数字大于0.100(当数字可能较小时)是没有意义的,也没有必要使用九的字符串来指示数字小于0.100(当数字可能更大时)。

将双精度转换为浮点数将选择其值范围包括双精度值所表示的双精度值范围的浮点数。请注意,虽然此操作是不可逆的,但操作的结果通常是正确的;唯一一次它不是100%的算术正确的时候是,如果一个人投掷浮动一个双倍,其范围精确地集中在两个浮点之间的边界上。在这种情况下,系统将选择双精度范围的一侧或另一侧的浮点数;如果双精度实际上表示范围错误一侧的数字,则生成的转换将略微不准确。

在实践中,上面提到的微小的不精确性几乎从不相关,因为浮点类型表示的“值范围”在实践中比上面指示的要大一些。对具有一定不确定性的两个数字执行计算(例如加法)将产生具有更多不确定性的结果,但系统不会跟踪存在多少不确定性。尽管如此,除非一个人对浮点数执行数十次操作,或对双精度执行数千次操作,否则不确定性通常小到不用担心。

重要的是要注意,将浮点数转换为双精度实际上比将双精度转换为浮点数要危险得多,即使Java允许在没有警告的情况下隐含地使用前者,但对后者发出争吵。将浮点数转换为双精度值会导致系统选择其范围以浮点数范围的中心为中心的双精度型。这几乎总是会得出一个实际不确定性远远大于双精度数字的典型值。例如,如果将 0.1f 转换为 double,则生成的 double 将表示 0.10000000149011611 到 0.10000000149011613 范围内的数字,即使它应该表示的数字(十分之一)相对而言远不及该范围。