gpt4 book ai didi

java - BigDecimal 对大于 7 或 0 小数的数字给出意想不到的结果

转载 作者:行者123 更新时间:2023-12-01 14:32:09 26 4
gpt4 key购买 nike

在尝试计算 2 个物体的体积比时,我注意到计算中有些奇怪,这里有一个您可以自己运行的示例:

public class TestApplication {

public static void main(String[] args) {
BigDecimal first = BigDecimal.valueOf(21099000.0);
BigDecimal second = BigDecimal.valueOf(13196000.0);

System.out.println("First: " + first);
System.out.println("Second: " + second);
System.out.println("Division: " + first.divide(second, RoundingMode.HALF_UP).doubleValue());
}
}

结果是:

First: 2.1099E+7
Second: 1.3196E+7
Division: 0.0

有 3 种方法可以让它给我预期的结果

<强>1。如果我将小数部分从 0 更改为 1(或任何非 0 数字):

First: 21099000.1
Second: 13196000.1
Division: 1.6

<强>2。如果我预先划分数字(将它们设为 7 位数字而不是 8 位数字):

First: 2109900.0
Second: 1319600.0
Division: 1.6

<强>3。如果我指定一个比例进行除法 (first.divide(second, 0, RoundingMode.HALF_UP):

First: 2.1099E+7
Second: 1.3196E+7
Division: 2.0

我认为 BigDecimal 由一个整数支持,而我使用的数字远低于 20 亿。谁能解释这 3 个案例与原始结果的不同之处?

最佳答案

根据 documentation , divide (BigDecimal divisor, RoundingMode roundingMode) 返回一个BigDecimal,其值为(this/divisor),其标度为this.scale().

为什么得到 21099000.1/13196000.1 的预期结果?

检查以下代码的结果:

import java.math.BigDecimal;
import java.math.RoundingMode;

public class Main {
public static void main(String[] args) {
BigDecimal first = BigDecimal.valueOf(21099000.1);
BigDecimal second = BigDecimal.valueOf(13196000.1);
System.out.println("First: " + first + ", Scale: " + first.scale());
System.out.println("Second: " + second + ", Scale: " + second.scale());

// 21099000.0 / 13196000.0 = 1.5988936041
System.out.println(BigDecimal.valueOf(1.5988936041).setScale(first.scale(), RoundingMode.HALF_UP));
}
}

输出:

First: 21099000.1, Scale: 1
Second: 13196000.1, Scale: 1
1.6

如您所见,JVM 为 first 选择了 1 的比例,因此 divide 的结果(即 1.5988936041) 也设置为 1 等于 1.6RoundingMode.HALF_UP

为什么21099000.0/13196000.0没有得到预期的结果?

检查以下代码的结果:

import java.math.BigDecimal;
import java.math.RoundingMode;

public class Main {
public static void main(String[] args) {
BigDecimal first = BigDecimal.valueOf(21099000.0);
BigDecimal second = BigDecimal.valueOf(13196000.0);
System.out.println("First: " + first + ", Scale: " + first.scale());
System.out.println("Second: " + second + ", Scale: " + second.scale());

// 21099000.0 / 13196000.0 = 1.5988936041
System.out.println(BigDecimal.valueOf(1.5988936041).setScale(first.scale(), RoundingMode.HALF_UP));
}
}

输出:

First: 2.1099E+7, Scale: -3
Second: 1.3196E+7, Scale: -3
0E+3

如您所见,JVM 为 first 选择了 -3 的比例,因此 divide 的结果(即 1.5988936041) 也设置为 -3 等于 0 (或 0E+3) 和 RoundingMode .HALF_UP.

如何改变这种行为?

如文档中所述,划分的比例设置为 this.scale() 这意味着如果您将 first 的比例设置为 1,可以得到预期的结果。

import java.math.BigDecimal;
import java.math.RoundingMode;

public class Main {
public static void main(String[] args) {
BigDecimal first = BigDecimal.valueOf(21099000.0).setScale(1);
BigDecimal second = BigDecimal.valueOf(13196000.0);
System.out.println("First: " + first + ", Scale: " + first.scale());
System.out.println("Second: " + second + ", Scale: " + second.scale());
System.out.println("Division: " + first.divide(second, RoundingMode.HALF_UP).doubleValue());
}
}

输出:

First: 21099000.0, Scale: 1
Second: 1.3196E+7, Scale: -3
Division: 1.6

最常见的方式是什么?

最后一个例子运行良好,使用没有问题。然而,最常见的方法是使用divide (BigDecimal divisor, int scale, RoundingMode roundingMode)

import java.math.BigDecimal;
import java.math.RoundingMode;

public class Main {
public static void main(String[] args) {
BigDecimal first = BigDecimal.valueOf(21099000.0);
BigDecimal second = BigDecimal.valueOf(13196000.0);
System.out.println("First: " + first + ", Scale: " + first.scale());
System.out.println("Second: " + second + ", Scale: " + second.scale());
System.out.println("Division: " + first.divide(second, 1, RoundingMode.HALF_UP).doubleValue());
}
}

输出:

First: 2.1099E+7, Scale: -3
Second: 1.3196E+7, Scale: -3
Division: 1.6

关于java - BigDecimal 对大于 7 或 0 小数的数字给出意想不到的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62148997/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com