专栏首页面朝大海春暖花开double转换为int以及浮点型相加损失精度问题

double转换为int以及浮点型相加损失精度问题

最近在做支付相关模块的业务,数据库字段却使用的是double类型,其实也行,只要计算不在sql语句中进行,也是没有问题的。

预先的类属性设置的是Double类型,自己算的时候发现小数相加会出现损失精度的情况

如下情形

    @Test
    public void testDouble(){
        Double [] arr = {39.9d,50d,198d,39.9d};
        Double verify = 0d;
        for (Double aDouble : arr) {
            verify += aDouble ;
        }
        System.out.println(verify);
    }

输出的结果是:327.79999999999995  理应为:328

待着疑惑试了下js

一看是一个效果,精度都会缺失。百度了下,解释如下

产生原因:

    计算机并不能识别除了二进制数据以外的任何数据,无论我们使用何种编程语言,在何种编译环境下工作,都要先把源程序翻译成二进制的机器码后才能被计算机识别。

    而在存储浮点型数据时,会分为三部分进行存储:

  1. 符号位(Sign): 0代表正,1代表为负
  2. 指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储
  3. 尾数部分(Mantissa):尾数部分

    其中前两位分别为实数符号位和指数符号位,于是存储结构实际为如下:

             31                  30            29----23        22----0         

               实数符号位    指数符号位    指数位      有效数位

       但是,在将十进制浮点数转换为二进制浮点数时,小数的二进制有时也是不可能精确的,就如同十进制不能准确表示1/3,二进制也无法准确表示1/10,而double类型存储尾数部分最多只能存储52位,于是,计算机在存储该浮点型数据时,便出现了精度丢失。

  例如,11.9的内存存储大约为:1011. 1110011001100110011001100...

       而在进行浮点类数据计算的时候,浮点参与计算,会左移或右移n位,直到小数点移动到第一个有效数字的右边。于是11.9在转化为二进制后 小数点左移3位,就得到1. 011 11100110011001100110(精度丢失2)

       于是最终浮点型运算出现了精度丢失误差。

 解决方式,java中可以使用 BigDecimal 来解决

    @Test
    public void test3(){
        System.out.println(0.11+2001299.32);//非精确的输出
        BigDecimal bigDecimal1 = new BigDecimal(Double.toString(0.11));
        BigDecimal bigDecimal2 = new BigDecimal(Double.toString(2001299.32));
        System.out.println(bigDecimal1.add(bigDecimal2));//精确的输出
    }

这种方式可以解决,并且很完美,但是还有一种方式比较容易些,毕竟是金额,小数位只有两位,可以先将其扩大100倍,再进行计算,计算完毕之后再除100,也可以解决(这么不要脸的方式也只有我这么low的程序员使用了)

在计算的过程总遇到double转int的情况,总结了下实现的方式

    Double d = 1.7d;

    @Test
    public void test1(){
        // 这样会报错,因为double转换为字符串之后有.
        System.out.println(Integer.parseInt(d.toString()));
    }

    @Test
    public void test2_1(){
        // double 类型可以直接转为int类型
        double dd = 1.1;
        int ddd = (int)dd;
        System.out.println(ddd);
    }

    @Test
    public void test2_2(){
        // 可以通过强转进行转换,Double是包装类,不能直接进行强转,可以拆箱之后再次强转。
        int aa = (int)(Double.parseDouble(d.toString()));
        System.out.println(aa);
    }

    @Test
    public void test3(){
        // 这种方式最为简单
        System.out.println(d.intValue());
    }

    @Test
    public void test4(){
        DecimalFormat format1 = new DecimalFormat("#");
        String s = format1.format(d);
        System.out.println(s);
    }

    @Test
    public void test5(){
        DecimalFormat format1 = new DecimalFormat("#.#");
        String s = format1.format(1.35);
        System.out.println(s);
    }

    @Test
    public void test6(){
        DecimalFormat format1 = new DecimalFormat("0.000");
        String s = format1.format(1.35);
        System.out.println(s);
    }

DecimalFormat 要四舍五入需要加上 setRoundingMode(RoundingMode.HALF_UP); 网上是这么说的,但是自己测试默认就会四舍五入

特殊字符说明 “0” 指定位置不存在数字则显示为0 123.123 ->0000.0000 ->0123.1230 “#” 指定位置不存在数字则不显示 123.123 -> ####.#### ->123.123 “.” 小数点 “%” 会将结果数字乘以100 后面再加上% 123.123 ->#.00->1.3212%

 嗯,就这么个坑了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • C语言中有关double、float类型转换成int型,及取整,丢失精度问题

    我们先来看一个题目:求一维数组double rea[10]中所有元素的整数部分和小数部分之和。题目也不难,先看下答案:

    用户6755376
  • Java基础知识-基本数据类型相互转型

    这是我第一次系统性的总结java这门语言的基础知识用法,因本人经验有限,所以在总结的过程中如果有错误或者有歧义等等之类的问题,都可以联系我QQ:20801753...

    林老师带你学编程
  • Java Grammar:数据类型

    我们知道,Java是一种 强类型 语言,类型对于Java语言来说非常的重要不言而喻,在Java中,分为 基础数据类型 和 引用数据类型 ,其中基础数据类型分为了...

    山禾说
  • BigDecimal和BigInteger

    我们知道计算机都是以二进制的形式存储数据的,而我们日常则是使用十进制,那么我们的 数字 存进计算机则需一个进制转换的过程,这过程就会损失精度的,就导致浮点数不能...

    晚上没宵夜
  • Java基础篇(01):基本数据类型,核心点整理

    不使用New创建,声明一个非引用传递的变量,且变量的值直接置于堆栈中,大小不随运行环境变化,效率更高。使用new创建的引用对象存储在堆中。

    知了一笑
  • Java基础之关键字,标识符,注释,数据类型

    Java的关键字对java的编译器有特殊的意义,他们用来表示一种数据类型,或者表示程序的结构等。

    南风
  • 你以为用了BigDecimal后,计算结果就一定精确了?

    大家好,我是你们的跃哥。首先问大家一个问题,平时加减乘除用的大部分是不是int类型,如果遇到金额计算,你们用什么呢?想必做过电商的小伙伴们能马上回答,说用Big...

    程序员小跃
  • Java 中的基本数据类型详解

    今天我们正式开始每日一题系列,最先开始的专题是 Java SE 专题,很多人可能觉得不以为然,Java 有什么好准备的,人家不都是一言不合就框架运用、底层原理吗...

    周三不加班
  • 基本数据类型

    关于java的类型,这里讲解基本类型,引用类型较复杂,分开来讲,那么开始把,基本类型有8种:

    晚上没宵夜

扫码关注云+社区

领取腾讯云代金券