zoukankan      html  css  js  c++  java
  • 精确值避免使用float和double,使用BigDecimal

    实现将double类型的值转换为BigDecimal类型的值的不同途径以及各途径间的区别 

     一:有人可能认为在 Java 中写入 new BigDecimal(0.1) 所创建的 BigDecimal 正好等于 0.1(非标度值 1,其标度为 1), 

      但是它实际上等于 0.1000000000000000055511151231257827021181583404541015625。

      这是因为 0.1 无法准确地表示为 double(或者说对于该情况,不能表示为任何有限长度的二进制小数)。

      这样,传入 到构造方法的值不会正好等于 0.1(虽然表面上等于该值)。  

     二:另一方面,String 构造方法是完全可预知的:写入 new BigDecimal("0.1") 将创建一个 BigDecimal,

      它正好 等于预期的 0.1。因此,比较而言,通常建议优先使用 String 构造方法。  

     三:使用public static BigDecimal valueOf(double val) 

      使用 Double.toString(double) 方法提供的 double 规范的字符串表示形式将 double 转换为 BigDecimal。  

      这通常是将 double(或 float)转化为 BigDecimal 的首选方法,  因为返回的值等于从构造 BigDecimal(使用 Double.toString(double) 得到的结果)得到的值。

     1 package com;
     2 
     3 import java.math.BigDecimal;
     4 
     5 /**
     6  * Created by huyanxia on 2017/11/27.
     7  */
     8 public class TestBigDecimal {
     9     public static void main(String[] args) {
    10         //3.0300000000000002
    11         System.out.println(1.03 + 2);
    12         //3.0300000000000000266453525910037569701671600341796875
    13         System.out.println(new BigDecimal(1.03).add( new BigDecimal(2)));
    14         //3.03
    15         System.out.println(new BigDecimal("1.03").add( new BigDecimal("2")));
    16         //3.03
    17         System.out.println(BigDecimal.valueOf(new BigDecimal("1.03").add( new BigDecimal("2")).doubleValue()));
    18         /* float和double尤其不适合进行货币计算,原因在于我们的计算机是二进制的。浮点数没有办法是用二进制进行精确表示。
    19         我们的CPU表示浮点数由两个部分组成:指数和尾数,这样的表示方法一般都会失去一定的精确度,有些浮点数运算也会产生一定的误差。
    20         如:2.4的二进制表示并非就是精确的2.4。反而最为接近的二进制表示是 2.3999999999999999。浮点数的值实际上是由一个特定的数学公式计算得到的。*/
    21 
    22         /*解决: 使用BigDecimal、int或long进行货币计算,1.BigDecimal货币计算,BigDecimal的参数要以字符串而不是double
    23          2.以分为单位进行计算,而不是意愿为单位*/
    24 
    25         //可以买3个,还剩0.3999999999999999元。
    26         double funds = 1.00;
    27         int bought = 0;
    28         for(double price = 0.1; funds >= price; price +=0.1){
    29             funds -= price;
    30             bought ++;
    31         }
    32         System.out.println("可以买" + bought + "个,还剩" + funds +"元。");
    33 
    34         //可以买4个,还剩0.00元。
    35         BigDecimal TEN_CEN = new BigDecimal("0.1");
    36         BigDecimal funds1 = new BigDecimal("1.00");
    37         int bought1 = 0;
    38         for(BigDecimal price = TEN_CEN; funds1.compareTo(price) >= 0; price = price.add(TEN_CEN)){
    39             funds1 = funds1.subtract(price);
    40             bought1 ++;
    41         }
    42         System.out.println("可以买" + bought1 + "个,还剩" + funds1 +"元。");
    43 
    44         //可以买3个,还剩0.3999999999999999666933092612453037872910499572753906250元。
    45         BigDecimal TEN_CEN2 = new BigDecimal(0.1);
    46         BigDecimal funds2 = new BigDecimal(1.00);
    47         int bought2 = 0;
    48         for(BigDecimal price = TEN_CEN2; funds2.compareTo(price) >= 0; price = price.add(TEN_CEN2)){
    49             funds2 = funds2.subtract(price);
    50             bought2 ++;
    51         }
    52         System.out.println("可以买" + bought2 + "个,还剩" + funds2 +"元。");
    53 
    54         //可以买4个,还剩0元。
    55         int funds3 = 100;
    56         int bought3 = 0;
    57         for(int price = 10; funds3 >= price; price += 10){
    58             funds3 -= price;
    59             bought3 ++;
    60         }
    61         System.out.println("可以买" + bought3 + "个,还剩" + funds3 +"元。");
    62     }
    63 }
  • 相关阅读:
    Python实例---抽屉后台框架分析
    Python学习---Django的验证码
    Python学习---DjangoForm的总结大全
    思维导图---思维导图网站
    编码学习---代码OJ网站
    multiple definition of XXX情况分析
    Qt 之 pro 配置详解
    萨尔曼可汗 数学视频
    Android sendevent/getevent 用法
    inux 驱动程序开发中输入子系统总共能产生哪些事件类型(EV_KEY,EV_ABS,EV_REL)
  • 原文地址:https://www.cnblogs.com/zhima-hu/p/7905132.html
Copyright © 2011-2022 走看看