计算中出现精度问题

作者: SanY_cjp | 来源:发表于2018-07-10 15:15 被阅读0次

    title: JAVA浮点计算经验
    date: 2016-08-4

    • JS
    • JAVA
    • float

    当浮点数进行运算的时候由于十进制与二进制相互转换的问题,可能出现不等于想要的结果

    1当浮点数进行运算的时候由于十进制与二进制相互转换的问题,可能出现不等于想要的结果

    例如
    2.2 + 2.1 = 4.300000000000001
    0.1 + 0.2 = 0.30000000000000004
    首先是十进制与二进制转换的问题:
    小数转换为二进制
    要点:乘二取整,正序排列
    解释:对被转换的小数乘以2,取其整数部分(0或1)作为二进制小数部分,取其小数部分,再乘以2,又取其整数部分作为二进制小数部分,然后取小数部分,再乘以2,直到小数部分为0或者已经去到了足够位数。每次取的整数部分,按先后次序排列,就构成了二进制小数的序列
    例如把0.2转换为二进制,转换过程如图:
    10-2-0.2.gif
    0.2乘以2,取整后小数部分再乘以2,运算4次后得到的整数部分依次为0、0、1、1,结果又变成了0.2,
    若果0.2再乘以2后会循环刚开始的4次运算,所以0.2转换二进制后将是0011的循环,即:0.0011 0011 0011 0011…

    2 JS 数字丢失精度的原因

    js采用双精度存储(double precision),占用 64 bit。
    (1) 1位用来表示符号位
    (2) 11位用来表示指数
    (3) 52位表示尾数
    浮点数转换成十进制存在无限循环的情况,例如
    0.1 >> 0.0001 1001 1001 1001…(1001无限循环)
    0.2 >> 0.0011 0011 0011 0011…(0011无限循环)
    此时只能模仿十进制进行四舍五入了,但是二进制只有0和1两个,于是变为0舍1入。
    这即是计算机中部分浮点数运算时出现误差,丢失精度的根本原因。
    大整数的精度丢失和浮点数本质上是一样的,尾数位最大是52位,因此JS中能精准表示的最大整数是Math.pow(2, 53),
    十进制即 9007199254740992。
    大于 9007199254740992 的可能会丢失精度
    9007199254740992 >> 10000000000000...000 // 共计 53 个 0

    3 解决方案

    对于整数,前端出现问题的几率几乎没有(除非特别大超出精度范围),
    只要运算结果不超过Math.pow(2, 53) 就不会丢失精度。
    对于小数,前端出现问题的几率还是很多的,尤其在一些电商网站涉及到金额等数据。
    解决方式:
    把小数放到位整数(乘10倍数),再缩小回原来倍数(除10倍数)
    例如计算

      0.1 + 0.2
    

    应写为

      (0.1*10 + 0.2*10) / 10 == 0.3          
    

    相关文章

      网友评论

        本文标题:计算中出现精度问题

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