double精度的坑与BigDecimal
近期经常接触支付相关的功能,在开发及测试过程中,开始金额都使用的是double类型,而近期新进的需求存在支付时打折的情况,也就是会出现如 1.23元的情况,那么这时候问题来了,如果是直接使用1.23进行支付都是不存在问题的。而偏偏在支付前通常需要一些计算。我们的系统支持会员余额与三方支付(微信、支付宝)同时进行,比如一笔待支付的订单是12.8员,其中用户有5块钱的会员余额,剩下的7.8元通过三方支付进行(这里使用微信吧),那么就涉及到double减法,同时微信支付时需要将元转为分,就是7.8x100,这又涉及到了乘法,此时就出现了double精度计算的问题。如下例子:
double a = 12.3d;
double b = 5d;
System.out.println(a-b); // 7.300000000000001 double c= 1.13d;
System.out.println(c * 100); // 112.99999999999999
上面的计算存在了精度问题,这样计算还需要进行四舍五入,比较麻烦。因此我们想到使用BigDecimal来实现小数的计算。最简单的加减乘除运算如下,希望可以帮到遇到同样问题的童鞋:
package com.blacksonny.utils; import java.math.BigDecimal; /**
* Created by kk on 2015/12/28.<br>
*/
public class NumericUtils { /**
* double 加运算
*
* @param a
* @param b
* @return
*/
public static double add(double a, double b) {
BigDecimal b1 = new BigDecimal(Double.toString(a));
BigDecimal b2 = new BigDecimal(Double.toString(b));
return b1.add(b2).doubleValue();
} /**
* float 加运算
*
* @param a
* @param b
* @return
*/
public static float add(float a, float b) {
BigDecimal b1 = new BigDecimal(Double.toString(a));
BigDecimal b2 = new BigDecimal(Double.toString(b));
return b1.add(b2).floatValue();
} /**
* double 减运算
*
* @param a
* @param b
* @return
*/
public static double subtract(double a, double b) {
BigDecimal b1 = new BigDecimal(Double.toString(a));
BigDecimal b2 = new BigDecimal(Double.toString(b));
return b1.subtract(b2).doubleValue();
} /**
* float 减运算
*
* @param a
* @param b
* @return
*/
public static float subtract(float a, float b) {
BigDecimal b1 = new BigDecimal(Double.toString(a));
BigDecimal b2 = new BigDecimal(Double.toString(b));
return b1.subtract(b2).floatValue();
} /**
* double 乘运算
*
* @param a
* @param b
* @return
*/
public static double multiply(double a, double b) {
BigDecimal b1 = new BigDecimal(Double.toString(a));
BigDecimal b2 = new BigDecimal(Double.toString(b));
return b1.multiply(b2).doubleValue();
} /**
* float 乘运算
*
* @param a
* @param b
* @return
*/
public static float multiply(float a, float b) {
BigDecimal b1 = new BigDecimal(Double.toString(a));
BigDecimal b2 = new BigDecimal(Double.toString(b));
return b1.multiply(b2).floatValue();
} /**
* double 除运算
*
* @param a
* @param b
* @return
*/
public static double divide(double a, double b) {
BigDecimal b1 = new BigDecimal(Double.toString(a));
BigDecimal b2 = new BigDecimal(Double.toString(b));
return b1.divide(b2).doubleValue();
} /**
* float 除运算
*
* @param a
* @param b
* @return
*/
public static float divide(float a, float b) {
BigDecimal b1 = new BigDecimal(Double.toString(a));
BigDecimal b2 = new BigDecimal(Double.toString(b));
return b1.divide(b2).floatValue();
}
}
另外在javascript中也存在精度计算的问题,没有什么好的方法,计算时使用parseFloat先转换,再取精度,写法为 parseFloat(xx.xxx).toFixed(2); //2表示取两位小数。
同时对于常用的需要将一个double转为BigDecimal时,应该使用BigDecimal.valueOf(0.1), 或者new BigDecimal("0.1"), 而不要直接将double类型作为构造方法的入参传入,这种写法有精度的问题。
double精度的坑与BigDecimal的更多相关文章
- Java中关于 BigDecimal 的一个导致double精度损失的"bug"
背景 在博客 恶心的0.5四舍五入问题 一文中看到一个关于 0.5 不能正确的四舍五入的问题.主要说的是 double 转换到 BigDecimal 后,进行四舍五入得不到正确的结果: public ...
- java 常用类库:BigInteger大整数;BigDecimal大小数(解决double精度损失);
大整数BigInteger package com.zmd.common_class_libraries; import java.math.BigInteger; /** * @ClassName ...
- java float、double精度研究(转)
在java中运行一下代码System.out.println(2.00-1.10);输出的结果是:0.8999999999999999很奇怪,并不是我们想要的值0.9 再运行如下代码:System.o ...
- Java Double 精度问题总结
package Demo_1.Test_2; import java.math.BigDecimal; /** * @描述:Java Double 精度问题总结 * @详细描述:使用Java,doub ...
- Java面试官:兄弟,你确定double精度比float低吗?
我有一个朋友,叫老刘,戴着度数比我还高的近视镜,显得格外的"程序员":穿着也非常"不拘一格",上半身是衬衣西服,下半身是牛仔裤运动鞋. 我和老刘的感情非常好,每 ...
- 【Double】double精度问题和int、long除不尽取舍问题
看了老半天,真心没搞懂,留下几篇文章,后面继续跟进吧.... 一.如何理解double精度丢失问题? - 知乎 https://www.zhihu.com/question/42024389/answ ...
- js double 精度损失 bugs
js double 精度损失 bugs const arr = [ 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ]; // [ ...
- BigDecimal 解决double精度丢失问题(加减乘除)
package com.qcloud.component.publicservice.util; import java.math.BigDecimal; /** * 由于Java的简单类型不能够精确 ...
- float和double精度问题
System.out.println(new BigDecimal(253.90).doubleValue() * 100);25390.0精度正确 System.out.println(new Bi ...
随机推荐
- java设计模式---享元模式
享元模式 顾名思义:共享元对象.如果在一个系统中存在多个相同的对象,那么只需要共享一份对象的拷贝,而不必为每一次使用创建新的对象. 享元模式是为数不多的.只为提升系统性能而生的设计模式.它的主要作用就 ...
- C# 面向对象 , 继承
继承 class A { Console.WriteLine("hello world"); } class B:A { } 以上书写,表示B 是A 的子类, B 同时继承A 中 ...
- javascript:void(0)知多少
在做页面时,如果想做一个链接点击后不做任何事情,或者响应点击而完成其他事情,可以设置其属性 href = "#",但是,这样会有一个问题,就是当页面有滚动条时,点击后会返回到页面顶 ...
- 对echarts的简单封装
看了echarts的官网介绍:http://echarts.baidu.com/doc/example.html 看了网上人使用js对echarts的封装:http://blog.csdn.net/x ...
- Ecstore获取dbschema内容?
有时候在使用dbschema的时候,需要获取dbschema的结构.例如: 那么,我们可以这样写: 这样我就能获得 称呼 这个数组
- java JNI 的实现(1)-又进一步加深对JVM实现的理解
目录 概述 主要优点 主要缺点 JNI实现的简单例子 开发工具 简略步骤 1,在eclipse的 'java类' 中声明一个 'native方法'; 2,使用 'javah' 命令生成包含'nativ ...
- java事件处理
1.ActionEven事件 文本框,按钮,菜单项,密码框,单选按钮都可以出发ActionEvent事件 使用 addActionListener(ActionListener listen1) 来注 ...
- java学习笔记(11) —— Struts2与Spring的整合
1.右键 项目名称 —— MyEclipse —— Add Spring Capabilities 2.选取 Copy checked Library contents to project fold ...
- NT头 IMAGE_NT_HEADER
typedef struct_IMAGE_NT_HEADERS{ DWORD Signature; // 固定为 0x00004550 “PE00" IMAGE_FILE_HEADER Fi ...
- 一次awk脚本的重构
# 脚本功能说明: # . 检查URL中的域名是否是指定版本的域名 # . 对访问bid,authorid的游客身份排重,并累加其pv # 全局变量说明 # DOMIAN_LIST 是数组,key是要 ...