近期经常接触支付相关的功能,在开发及测试过程中,开始金额都使用的是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的更多相关文章

  1. Java中关于 BigDecimal 的一个导致double精度损失的"bug"

    背景 在博客 恶心的0.5四舍五入问题 一文中看到一个关于 0.5 不能正确的四舍五入的问题.主要说的是 double 转换到 BigDecimal 后,进行四舍五入得不到正确的结果: public ...

  2. java 常用类库:BigInteger大整数;BigDecimal大小数(解决double精度损失);

    大整数BigInteger package com.zmd.common_class_libraries; import java.math.BigInteger; /** * @ClassName ...

  3. java float、double精度研究(转)

    在java中运行一下代码System.out.println(2.00-1.10);输出的结果是:0.8999999999999999很奇怪,并不是我们想要的值0.9 再运行如下代码:System.o ...

  4. Java Double 精度问题总结

    package Demo_1.Test_2; import java.math.BigDecimal; /** * @描述:Java Double 精度问题总结 * @详细描述:使用Java,doub ...

  5. Java面试官:兄弟,你确定double精度比float低吗?

    我有一个朋友,叫老刘,戴着度数比我还高的近视镜,显得格外的"程序员":穿着也非常"不拘一格",上半身是衬衣西服,下半身是牛仔裤运动鞋. 我和老刘的感情非常好,每 ...

  6. 【Double】double精度问题和int、long除不尽取舍问题

    看了老半天,真心没搞懂,留下几篇文章,后面继续跟进吧.... 一.如何理解double精度丢失问题? - 知乎 https://www.zhihu.com/question/42024389/answ ...

  7. 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 ]; // [ ...

  8. BigDecimal 解决double精度丢失问题(加减乘除)

    package com.qcloud.component.publicservice.util; import java.math.BigDecimal; /** * 由于Java的简单类型不能够精确 ...

  9. float和double精度问题

    System.out.println(new BigDecimal(253.90).doubleValue() * 100);25390.0精度正确 System.out.println(new Bi ...

随机推荐

  1. 【网络流#1】hdu 3549 - 最大流模板题

    因为坑了无数次队友 要开始学习网络流了,先从基础的开始,嗯~ 这道题是最大流的模板题,用来测试模板好啦~ Edmonds_Karp模板 with 前向星 时间复杂度o(V*E^2) #include& ...

  2. centos redis安装

    对redis不是很了解,先写一个简单的安装过程 系统版本:centos 6.5 redis版本:2.8.23 一.安装依赖 sudo yum install tcl gcc gcc-c++ -y 二. ...

  3. 类名.this与类名.class

    1..当在内部类中使用this指的就是内部类的对象, 为了访问外层类对象,就可以使用外层类名.this来访问. 2.在java中,每个class都有一个相应的Class对象,当编写好一个类,编译完成后 ...

  4. 利用eclipse开发php<转>

    1.安装php环境 Eclipse支持PHP自动提示 其实如果你已经安装好了php环境(安装过程见)的话,只需要下面2步就可以了.hoho,很简单的. 1,下载eclipse中php的插件phpecl ...

  5. linux 第二天

    文件权限和用户组 groupadd 组名 groupadd policeman 查看组 vi /etc/group cat /etc/group 创建用户,并同时指定将该用户分配到哪个组 userad ...

  6. 全世界最详细的一步一步搭建RAC步骤(一)---安装操作系统RHEL4.6【weber出品】

    全文搭建RAC分为3步骤 <--安装操作系统RHEL4.6> <--配置ASM+裸设备> <--安装集群软件>       <--安装数据库软件>   ...

  7. ORA-19502: write error on file "/u01/app/oracle/oradata/standby/system01.dbf", blockno 40321 (blocksize=8192)【error收集】

    在RMAN备份中,出现了一个问题,就是出现坏块了. ORA-: write error on file (blocksize=) ORA-: File I/O error Linux Error: : ...

  8. 《Linux内核分析》 week8作业-Linux加载和启动一个可执行程序

    一.ELF文件格式 ELF(Executable and Linking Format)是x86 Linux系统下常用的目标文件格式,有三种主要类型: 适于连接的可重定位文件,可与其他目标文件一起创建 ...

  9. VS2010 IE10 调试时报“未能将脚本调试器附加到计算机”,已经附加了一个进程

    解决办法:以管理员身份打开CMD,运行:regsvr32.exe "%ProgramFiles(x86)%\Common Files\Microsoft Shared\VS7Debug\ms ...

  10. PowerShell: 如何解决File **.ps1 cannot be loaded because the execution of scripts is disabled on this sy

    PowerShell 默认不允许执行*.ps1脚本文件.运行ps1文件会得到下面的错误: File C:\Temp\Test.ps1 cannot be loaded because the exec ...