Double和Float运算以及DecimalFormat格式化精度丢失踩坑记录

一、double和float直接进行运算会丢失精度

double d = 0.58;
// 57.99999999999999 精度丢失
System.out.println(d * 100);
double d2 = 65.21;
// 0.6520999999999999 精度丢失
System.out.println(d2 / 100);
float f = 0.05f;
float f1 = 0.01f;
// 0.060000002 丢失精度
System.out.println(f + f1);

二、double和float封装成BigDecimal进行运算可以保留精度,但必须以String类型为入参的构造器构造BigDecimal对象才行。

double d = 0.58;
// 57.99999999999999 精度丢失
System.out.println(d * 100);
// 其他double、int、long构造器都会进行舍入,丢失精度
BigDecimal decimal = new BigDecimal(d);
// 必须为String的构造器才不会丢失精度
BigDecimal decimal2 = new BigDecimal(String.valueOf(d));
// 57.99999999999999 精度丢失
System.out.println(decimal.multiply(new BigDecimal(100)).doubleValue());
// 58.0 精度没有丢失
System.out.println(decimal2.multiply(new BigDecimal(100)).doubleValue());
BigDecimal.valueOf内部用的就是String类型参数的构造器,所以用BigDecimal.valueOf可以保留精度
double d2 = 65.21;
// 0.6520999999999999 精度丢失
System.out.println(d2 / 100);
// 0.6521 不会丢失精度,内部会转换为String的构造器
System.out.println(BigDecimal.valueOf(d2).divide(BigDecimal.valueOf(100)));
// 丢失精度
System.out.println(new BigDecimal(d2).divide(BigDecimal.valueOf(100)));

三、float强转double也会丢失精度,float需要先转成String,再转成double,就不会丢失精度

float f = 0.05f;
float f1 = 0.01f;
// 0.060000002 丢失精度
System.out.println(f + f1);
// 0.060000000521540642 丢失精度,float直接转double会涉及精度问题
System.out.println(BigDecimal.valueOf(f).add(BigDecimal.valueOf(f1)));
// 0.06 不丢失精度
System.out.println(new BigDecimal(String.valueOf(f)).add(new BigDecimal(String.valueOf(f1))));
double d = f;
// 0.05000000074505806, float直接转double会丢失精度
System.out.println(d);
double d2 = Double.parseDouble(String.valueOf(f));
// 0.05 float -> String -> double 不会丢失精度
System.out.println(d2);

四、DecimalFormat对double进行格式化时,也可能会丢失精度。需要设置decimalFormat.setParseBigDecimal(true),以BigDecimal去解析,就不会丢失精度

String pattern = "#.##%";
DecimalFormat decimalFormat = new DecimalFormat(pattern);
Number num = decimalFormat.parse("65.21%");
// Double: 0.6520999999999999 丢失精度
System.out.println(num.getClass().getSimpleName() + ": " + num);
// 设置DecimalFormat以BigDecimal去解析,不会丢失精度
decimalFormat.setParseBigDecimal(true);
Number n = decimalFormat.parse("65.21%");
// BigDecimal: 0.6521 没有丢失精度
System.out.println(n.getClass().getSimpleName() + ": " + n);

五、DecimalFormat格式化用例

      //#:比实际数字的位数多,不变。比实际数字的位数少:整数部分不改动,小数部分,四舍五入
      String pattern = "#.##%";
      DecimalFormat decimalFormat = new DecimalFormat(pattern);
      System.out.println(decimalFormat.parse("2.4%"));//0.024
      System.out.println(decimalFormat.format(0.6521));//65.21%
      System.out.println(decimalFormat.format(0.652566));//65.26%
      System.out.println(new DecimalFormat("##.##").format(3.14));//3.14
      System.out.println(new DecimalFormat("##.#").format(3.14));//3.1
      System.out.println(new DecimalFormat("##.#").format(323.14));//323.1
      //0:比实际数字的位数多,不足的地方用0补上,比实际数字的位数少:整数部分不改动,小数部分,四舍五入
      System.out.println(new DecimalFormat("00.00").format(3.14));//03.14
      System.out.println(new DecimalFormat("00.000").format(3.14));//03.140
      System.out.println(new DecimalFormat("00.0").format(3.14));//03.1
      System.out.println(new DecimalFormat("0.0").format(3.14));//3.1
      System.out.println(new DecimalFormat("#.00%").format(13.146));//1314.60%

      long c = 299792458;
      //五位小数科学计数法2.99792E8
      System.out.println(new DecimalFormat("#.#####E0").format(c));
      //两位整数四位小数29.9792E7
      System.out.println(new DecimalFormat("00.####E0").format(c));
      //每三位用逗号隔开
      System.out.println(new DecimalFormat(",###").format(c));
      //和文本拼接
      System.out.println(new DecimalFormat("光速大小为:###m/s").format(c));

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值