BigDecimal 初始化后的 Stange 值
Stange values after BigDecimal initialization
我正在尝试通过以下方式初始化 HashMap:
HashMap<BigDecimal,BigDecimal> myMap = new HashMap<>();
myMap .put(new BigDecimal(1.7), new BigDecimal(1.5));
myMap .put(new BigDecimal(3.3), new BigDecimal(3));
myMap .put(new BigDecimal(5), new BigDecimal(4.5));
myMap .put(new BigDecimal(6.6), new BigDecimal(6));
myMap .put(new BigDecimal(11), new BigDecimal(10));
myMap .put(new BigDecimal(16.5), new BigDecimal(15));
但是插入上面的值在以下 wang 中发生了变化:
1.7 becomes 1.6999999999999999555910790149937383830547332763671875
3.3 becomes 3.29999999999999982236431605997495353221893310546875
6.6 becomes 6.5999999999999996447286321199499070644378662109375
为什么会这样?
1.7
等是一个浮点双字面值。 1.7 不能完全表示为 double
.
它最接近 1.7 的值被传递给 BigDecimal
构造函数。 BigDecimal
能够表示这种不精确性,从而给出观察到的效果。
1.5
是一个 二元有理数 ,因此 可以 准确表示。
一种补救措施是使用 BigDecimal
构造函数,该构造函数接受 double
和 MathContext
对象:这允许您控制舍入行为。
另一种补救方法是使用BigDecimal.valueOf(1.7)
。在内部,这将通过字符串利用转换。虽然易于处理,但计算量大。
使用 BigDecimal.valueOf(double)
静态方法:这将从您需要的双精度数字的字符串表示形式初始化 BigDecimal
。
不要使用 constructor which takes a double , but the with String
根据双构造函数的文档:
The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal(0.1) in Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding.
您可以使用以下代码使用 BigDecimal 初始化 HashMap。
HashMap<BigDecimal, BigDecimal> myMap = new HashMap<>();
myMap.put(BigDecimal.valueOf(1.7), BigDecimal.valueOf(1.5));
myMap.put(BigDecimal.valueOf(3.3), BigDecimal.valueOf(3));
myMap.put(BigDecimal.valueOf(3), BigDecimal.valueOf(4.5));
myMap.put(BigDecimal.valueOf(6.6), BigDecimal.valueOf(6));
myMap.put(BigDecimal.valueOf(11), BigDecimal.valueOf(10));
myMap.put(BigDecimal.valueOf(16.5), BigDecimal.valueOf(15));
Set set1 = myMap.entrySet();
Iterator it1 = set1.iterator();
while (it1.hasNext()) {
Map.Entry meEntry = (Map.Entry) it1.next();
System.out.println("key is: " + meEntry.getKey() + " & Value is: " + meEntry.getValue());
}
我正在尝试通过以下方式初始化 HashMap:
HashMap<BigDecimal,BigDecimal> myMap = new HashMap<>();
myMap .put(new BigDecimal(1.7), new BigDecimal(1.5));
myMap .put(new BigDecimal(3.3), new BigDecimal(3));
myMap .put(new BigDecimal(5), new BigDecimal(4.5));
myMap .put(new BigDecimal(6.6), new BigDecimal(6));
myMap .put(new BigDecimal(11), new BigDecimal(10));
myMap .put(new BigDecimal(16.5), new BigDecimal(15));
但是插入上面的值在以下 wang 中发生了变化:
1.7 becomes 1.6999999999999999555910790149937383830547332763671875
3.3 becomes 3.29999999999999982236431605997495353221893310546875
6.6 becomes 6.5999999999999996447286321199499070644378662109375
为什么会这样?
1.7
等是一个浮点双字面值。 1.7 不能完全表示为 double
.
它最接近 1.7 的值被传递给 BigDecimal
构造函数。 BigDecimal
能够表示这种不精确性,从而给出观察到的效果。
1.5
是一个 二元有理数 ,因此 可以 准确表示。
一种补救措施是使用 BigDecimal
构造函数,该构造函数接受 double
和 MathContext
对象:这允许您控制舍入行为。
另一种补救方法是使用BigDecimal.valueOf(1.7)
。在内部,这将通过字符串利用转换。虽然易于处理,但计算量大。
使用 BigDecimal.valueOf(double)
静态方法:这将从您需要的双精度数字的字符串表示形式初始化 BigDecimal
。
不要使用 constructor which takes a double , but the with String
根据双构造函数的文档:
The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal(0.1) in Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding.
您可以使用以下代码使用 BigDecimal 初始化 HashMap。
HashMap<BigDecimal, BigDecimal> myMap = new HashMap<>();
myMap.put(BigDecimal.valueOf(1.7), BigDecimal.valueOf(1.5));
myMap.put(BigDecimal.valueOf(3.3), BigDecimal.valueOf(3));
myMap.put(BigDecimal.valueOf(3), BigDecimal.valueOf(4.5));
myMap.put(BigDecimal.valueOf(6.6), BigDecimal.valueOf(6));
myMap.put(BigDecimal.valueOf(11), BigDecimal.valueOf(10));
myMap.put(BigDecimal.valueOf(16.5), BigDecimal.valueOf(15));
Set set1 = myMap.entrySet();
Iterator it1 = set1.iterator();
while (it1.hasNext()) {
Map.Entry meEntry = (Map.Entry) it1.next();
System.out.println("key is: " + meEntry.getKey() + " & Value is: " + meEntry.getValue());
}