Java浮点乘法给出错误的结果



使用FLOAT的乘法产生了明显的差异。


public static void main(String[] args) {
// using string and parsing instead of actual data type is part of use case, that is why representing the same here
double v1 = parseDouble("590.0");
double v2 = parseDouble("490.0");
double v3 = parseDouble("391.0");
float v4 = parseFloat("590.0");
float v5 = parseFloat("490.0");
float v6 = parseFloat("391.0");
System.out.println(new BigDecimal(v1 * v2 * v3));
System.out.println(new BigDecimal(v4 * v5 * v6));
System.out.println(BigDecimal.valueOf(Float.parseFloat("289100.0") * Float.parseFloat("391.0")));
System.out.println(BigDecimal.valueOf(Double.parseDouble("289100.0") * Double.parseDouble("391.0")));
}

输出:

113038100 // double multiplication
113038096 // float multiplication
113038096
113038100

对于上述代码,

(590.0*490.0*391.0)使用双得到113038100

(590.0*490.0*391.0)使用浮动(113038100-113038096=4//差)给出11303809

我已经通读了https://floating-point-gui.de/basic/这个链接能够理解浮点计算是如何发生的,而所有4个计数的不同是出乎意料的。

请帮助我理解以下内容

  • 这首先正确吗
  • 浮点总是给出错误的数字吗
  • 正如我所看到的,double也使用相同的技术,所以如果我们使用double,我们有多大的保证才能得到正确的结果

是否总是float给出错误的数字??

它取决于数字,如果数字可以用浮点精度表示,那么它将是精细的

"正如我所看到的,替身也使用相同的技术,那么我们有多少保证如果我们使用double";

double也有同样的问题,但由于double的精度更高,可能性更低,但仍会发生

因此,当你需要一个非常精确的结果时,比如在科学或金融应用程序中,你需要使用BigDecimal

看这个视频,它解释浮点数是如何工作的https://www.youtube.com/watch?v=ajaHQ9S4uTA

这是正确的第一个吗

Javafloat格式为IEEE-754二进制32。在这种格式中,每个有限数都表示为一个符号、一个24位整数和一个从2-149到2104的二次幂缩放。整数部分称为有效位。(该格式通常被描述为一个符号,一个24位的数字,在第一位之后有一个二进制点,所以它的值在[0,2)中,并且从2-126到2127。这些在数学上是等效的,这里使用的格式在IEEE-754标准中作为一个选项进行了说明。)在正常形式下,24位整数是223或更大。(小于2-126的可表示数不能用正规形式表示,必须是次正规的。)

在这种格式中,590可以表示为+590•20或+8339456•2−14。490为+490•20或+16056320•2−15。

它们的乘积为+289100•20或+9251200•2−5。

391为+391•20或+12821288-15

+289100•20和+391•20的普通算术乘积为+113038100•20。但是,113038100不是一个24位数字;它是一个27位的数字。要使其低于224,我们可以调整缩放比例,将有效位乘以⅛并且将缩放乘以8=23

这给了我们+14129762.5•23。然而,现在有效位不是整数。该结果不能用float格式表示。为了产生结果,定义了float格式的加法运算,以将普通算术四舍五入到最接近的可表示值。在这种情况下,有一个平局,我们可以四舍五入上升或下降。平局是通过四舍五入来解决的,以使低数位偶数,因此我们四舍五舍五入到+14129762•23

+14129762•23为113038096。这就是你得到的结果,所以它是正确的。

是否总是float给出错误的数字??

这没有错;这台计算机按其规格运行。

观察float是一个32位的格式,但是有无限多的实数。甚至有无限多的有理数。32位格式不可能产生与理论实数算术或有理数算术相同的结果。可能的结果比可表示的值多。

64位double格式也是如此。整数格式、固定精度格式以及所有位数固定的数字格式也是如此。固定数量的比特不能表示无限多的值。

您的评论表明,您认为浮点运算会为小于1的小数产生近似结果。但是,对可以表示多少值的限制适用于所有尺度。在每个标度(每二次方)上,只有224的值是可表示的(2<sup]23>为正态)。对于标度20,所有低于224的非负整数都是可表示的。但是,除此之外,只有一些整数是可表示的。一开始,我们必须跳过每二个整数,然后跳过每四个整数,再跳过每八个整数,依此类推

浮点运算是为了逼近实数运算而设计的。当您想要近似实数算术时,应该使用它。当您想要精确的算术运算时,不应该使用它,除非极少数例外。

相关内容

  • 没有找到相关文章

最新更新