代码之家  ›  专栏  ›  技术社区  ›  riv

JS如何将大数(2^53以上)转换为字符串

  •  3
  • riv  · 技术社区  · 8 年前

    printf("%lf",(double)(1LL<<55)) 在C中,将正确打印该数字,因为它的二进制表示形式中有尾随的零,在截断时不会导致精度损失。

    规范中有没有定义这种奇怪行为的地方?

    1 回复  |  直到 8 年前
        1
  •  1
  •   NullPointer    8 年前

    问题- 既然2^53以上的整数不能用双精度表示,那么当它们被打印成字符串时,JS如何决定它们的十进制表示呢?



    JavaScript数字在内部以二进制浮点形式存储,通常以十进制显示。

    JavaScript使用两种十进制符号:

    [ "+" | "-" ] digit+ [ "." digit+ ]
    

    指数记数法

    [ "+" | "-" ] digit [ "." digit+ ] "e" [ "+" | "-" ] digit+
    

    1.2345678901234568e+21 .

    显示小数的规则:

    如果小数点前有超过21位数字,则使用指数表示法。

    如果数字以0开头,后跟五个以上的零,则使用指数表示法。


    2.安全 ECMAScript 5.1 显示算法

    给定一个数字

    mantissa × 10^pointPos−digitCount
    

    浮点数的尾数是一个有效数字加上一个符号的整数。前导零和尾随零被丢弃。示例:

    案例一。 无小数点: digitCount ≤ pointPos ≤ 21 打印数字(不带前导零),后跟pointPosdigitCount零。

    案例二。 尾数内的小数点 0 < pointPos ≤ 21, pointPos < digitCount 显示尾数的第一个数字,一个点,然后是剩余的数字countpointpos。

    案例3。 小数点在尾数之前 −6 < pointPos ≤ 0 显示一个0,后跟一个点,pointPos零和尾数。

    案例4。 指数记数法 : pointPos ≤ -6 or pointPos > 21 显示尾数的第一个数字。如果有更多的数字,则显示一个点和剩余的数字。接下来,显示字符e和加号或减号(取决于pointPos1的符号),后跟pointPos1的绝对值。因此,结果如下所示。

    mantissa0 [ "." mantissa1..digitCount ] 
         "e" signChar(pointPos−1) abs(pointPos−1)
    

    问题- 然而,在Javascript中,我们得到的是36028797018963970。它似乎试图对数字进行四舍五入以在结尾处得到一个0,但并不总是这样——例如,2^55-4在结尾处用4来正确表示。



    支票: How numbers are encoded in JavaScript 5.最大整数


    附加参考: https://medium.com/dailyjs/javascripts-number-type-8d59199db1b6