JavaScript浮点数的精度问题深究

作者: 陈学谦_ | 来源:发表于2019-01-20 00:42 被阅读3次

    JavaScript浮点数的精度问题

    javascript浮点数的精度问题是老生常谈了,但往往只知道0.1 + 0.2 != 0.3,究其原因,只能说出javascript精度问题,知其然而不知其所以然。
    比如我,知道小数运算会有精度问题,但不知道整数运算同样会出现精度问题

    82234342434234235339 + 23338435345455243948
    // 结果
    105572777779689490000
    

    究其原因,网上看了些文章,但好多细节略过了,让我这种没有预备知识的看的一脸懵逼。比如十进制0.1转换成二进制咋转的?干,没说

    javascript中的Number

    在javascript中,数值类型都是Number,无论是整数还是浮点数。Number采用的是IEEE 754标准的64 位双精度浮点数。往往解释js精度问题基本上就只能说道这了,但我还是不明白为什么呀?

    IEEE 754标准的64 位双精度浮点数

    首先有一个概念需要明确,64位双精度的意思是:因为它是64位的,所以它是双精度。如果是32位,则是单精度的。(类似于Java中的float和double)

    js采用的这种浮点数,一个数字由64位组成,你可以理解成:
    00000011101...0001011001这么一串

    那我们数字得有正负吧?这个这种浮点数它用第0位来表示正负。0表示正数,1表示负数

    接下来第1位~第11位用来表示指数第12位~第63位表示有效数字。如下图

    img

    小数的精度问题

    我们先来看0.1+0.2的运算过程是怎样的。

    • 0.1和0.2转为二进制表示
    • 将两个二进制数相加
    • 将结果转为十进制

    关于十进制小数如何转成二进制可以看这篇文章,很简单的。
    当你把0.1转为二进制的时候你会发现,这货居然无穷的。(实际输出可以直接在控制台尝试:(0.1).toString(2))

    但是我们刚刚说了,js采用的这种浮点数表示法,有效数字只有52位,也就是0.1转成二进制以后最终只能保留小数点后52位,如下:

    0.1 -> 0.0001100110011001100110011001100110011001100110011001
    
    0.2 -> 0.0011001100110011001100110011001100110011001100110011
    

    只要你试过,你就会开心的发现,0.1~0.9,除了0.5以外,都是无穷的,nice。

    如果你不想自己计算两个二进制数相加,可以用我写的twoBigIntSum方法将两个位数相加

    那么0.1 + 0.2最终得到的就是

    0.0100110011001100110011001100110011001100110011001100

    把它转为十进制是0.30000000000000004,开不开心,意不意外。

    整数精度问题

    最让我诧异的是整数居然也会有精度问题,看两个例子:

    19571992547450991 === 19571992547450990 // true
    输入:82234342434234235339 -> 输出:82234342434234240000
    

    道理和小数的精度问题是一样的,有效数只有52位,也就是整数的安全范围是-2^53 - 1~2^53 - 1(52位都为1),超出这个范围的整数精度就会出现问题。javascript中也提供了Number.MAX_SAFE_INTEGER接口,返回在安全范围内的最大整数。

    是不是很刺激?

    回到我们开头的问题:

    82234342434234235339 + 23338435345455243948
    // 结果
    105572777779689490000
    

    这是为什么呢?

    就是因为这两个数超出了安全范围

    82234342434234235339 --实际上等于--> 82234342434234240000
    23338435345455243948 --实际上等于--> 23338435345455243000
    将两数相加又出现精度问题,所以最后加和得到
    105572777779689490000
    

    相关文章

      网友评论

        本文标题:JavaScript浮点数的精度问题深究

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