Stange values after BigDecimal initialization

微笑、不失礼 提交于 2021-01-28 19:15:30

问题


I'm trying to initialize a HashMap in the foolowing way:

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));

but tha value above insert are change in the following wang:

1.7 becomes 1.6999999999999999555910790149937383830547332763671875
3.3 becomes 3.29999999999999982236431605997495353221893310546875
6.6 becomes 6.5999999999999996447286321199499070644378662109375

Why is happening this?


回答1:


Use BigDecimal.valueOf(double) static method: this will initialize the BigDecimal from string representation of the double number which is what you need.




回答2:


Don't use the constructor which takes a double , but the with String

as per doc for the double constructor:

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.




回答3:


1.7 etc. is a floating point double literal. 1.7 cannot be represented exactly as a double.

Its closest approximation to 1.7 is being passed to the BigDecimal constructor. And BigDecimal is capable of representing that imprecision so giving the observed effect.

1.5 is a dyadic rational and so can be represented exactly.

One remedy is to use the BigDecimal constructor that takes a double along with a MathContext object: this allows you to control the rounding behaviour.

Another remedy is to use BigDecimal.valueOf(1.7). Internally this will exploit conversion via a string. Although tractable, it is computationally expensive.




回答4:


You can use below code to initialize a HashMap using BigDecimal.

    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());

    }


来源:https://stackoverflow.com/questions/31853423/stange-values-after-bigdecimal-initialization

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!