美文网首页
货币计算请避免使用float和double

货币计算请避免使用float和double

作者: 大头8086 | 来源:发表于2017-12-01 23:10 被阅读1467次

最近做了一个有关接入微信支付的需求,其中微信支付接口的有关金额的字段值单位都为分,如下红框所示。

image.png

一般我们业务保存和展示的金额单位都是元,值包含小数点。所以在调用微信支付接口时我们要把单位为元的金额(Double类型)转成单位为分的金额(Integer类型),涉及到浮点运算,在开发中踩了一个坑,与大家分享。

刚开始使用Double计算货币金额,如下代码所示:

public class DoubleTest {

    public static void main(String[] args) {
        double yuanDouble = 10.2d;
        System.out.println(yuanDouble);
        double fenDouble = yuanDouble * 100;
        System.out.println(fenDouble);
        int fenInteger = (int)fenDouble; // 截断成int
        System.out.println(fenInteger);
    }
}

执行结果如下,单位为元的10.2转成单位为分的1019,发生精度资损。

10.2
1019.9999999999999
1019

因此,float和double类型主要是为了科学计算和工程计算而设计的。他们执行二进制浮点运算,这是为了在广泛的数字范围上提供较为精确的快速近似计算而精心设计的。然而,它们并没有提供完全精确的结果,所以我们不应该用于精确计算的场合。float和double类型尤其不适合用于货币运算,因为要让一个float或double精确的表示0.1或者10的任何其他负数次方值是不可能的(其实道理很简单,十进制系统中能不能准确表示出1/3呢?同样二进制系统也无法准确表示1/10)。

浮点运算很少是精确的,只要是超过精度能表示的范围就会产生误差。往往产生误差不是因为数的大小,而是因为数的精度。因此,产生的结果接近但不等于想要的结果。尤其在使用 float 和 double 作精确运算的时候要特别小心,比如货币金额计算。

解决这个问题的正确办法是使用BigDecimal进行货币金额计算,示例如下:

import java.math.BigDecimal;
public class DoubleTest {

    private static double mul(double d1,double d2){
        BigDecimal bd1 = new BigDecimal(Double.toString(d1));
        BigDecimal bd2 = new BigDecimal(Double.toString(d2));
        return bd1.multiply(bd2).doubleValue();
    }

    public static void main(String[] args) {
        double yuanDouble = 10.2d;
        System.out.println(yuanDouble);
        double fenDouble = mul(yuanDouble, 100);
        System.out.println(fenDouble);
        int fenInteger = (int)fenDouble; // 截断成int
        System.out.println(fenInteger);
    }
}

运行结果如下,这才是正确的货币金额计算方式。

10.2
1020.0
1020

但是,使用BigDecimal有两个缺点:与使用基本运算类型相比,这样做很不方便,而且很慢。对于解决货币计算的精度问题,后一种缺点并不要紧,但是前一种缺点可能会让你使用很不舒服。

总之,对于任何需要精度答案的计算任务,比如货币计算,请不要使用float或者double。如果你想让系统记录十进制小数点,并且不介意因为不使用基本类型而带来的不便,就请使用BigDecimal。

相关文章

  • 货币计算请避免使用float和double

    最近做了一个有关接入微信支付的需求,其中微信支付接口的有关金额的字段值单位都为分,如下红框所示。 一般我们业务保存...

  • 提示60-61

    第60条:如果需要精确的答案,请避免使用float和double float和double类型主要是为了科学计算和...

  • 关于BigDecimal

    使用double和float计算时会造成精度丢失的问题 要进行计算要用BigDecimalBigdecimal a...

  • BigDecimal的使用

    float、double 用于科学计算或工程计算 涉及金额的精确计算(商业计算),使用java.math.BigD...

  • iOS中的高精度数值计算

    前言 在iOS开发中,和价格计算相关的,需要注意计算精度的问题,使用float、double来计算价格数值会出现精...

  • java BigDecimal 学习及用法

    情况 一般情况下使用double和float计算时总是精度改变问题困扰着开发者们,以及使用金额计算的情况要求开发者...

  • [java 基础]BigDecimal

    场景说明 在进行金额表示、金额计算时,不能使用double,float,要使用对精度支持更好的BigDecimal...

  • iOS中常用的数学函数

    每一个函数都有对应计算float / double / long double 的函数,这里只列出double类型...

  • 在 Java 中解开你的字符串

    在任何编程语言中,要执行任何类型的计算,您总是使用数值(Int、float、double 等)、布尔和字符串类型的...

  • iOS中常用的数学函数

    每一个函数都有对应计算float / double / long double 的函数,这里只列出double类型的

网友评论

      本文标题:货币计算请避免使用float和double

      本文链接:https://www.haomeiwen.com/subject/ahjgbxtx.html