如何在Javascript中避免小整数溢出

cyb*_*bat 13 javascript

我正在阅读Douglas Crockford的书 - Javascript的好部分 - 他说:

JavaScript有一个数字类型.在内部,它表示为64位浮点,与Java的double相同.与大多数其他编程语言不同,没有单独的整数类型,因此1和1.0是相同的值.这是一个很大的便利,因为完全避免了短整数溢出的问题......

我不太熟悉其他语言,所以想要一点解释.我能理解为什么64位有帮助,但他的陈述似乎适用于缺少浮点数和双打.

什么是(伪代码)可能是JS中不会出现的短整数溢出情况的例子?

And*_*erd 8

假设你有一个8位无符号数.

以下是一系列数字和二进制表示:

1:00000001

2:00000010

15:00001111

255:11111111

如果您有255并添加1,会发生什么?没有更多的位,所以它包裹着

0:00000000

这是使用uint(无符号32位整数)在C#中的演示

using System;

public class Program
{
    public static void Main()
    {
        uint n = 4294967294;
        for(int i = 0; i < 4; ++i)
        {
            n = n + 1;
            Console.WriteLine("n = {0}", n); 
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

这将输出:

n = 4294967294
n = 4294967295
n = 0
n = 1
Run Code Online (Sandbox Code Playgroud)

这是你在JavaScript中没有得到的问题.


你会遇到不同的问题.

例如:

var n = 9007199254740991;
var m = n + 1;
var p = m + 1;
alert('n = ' + n + ' and m = ' + m + ' and p = ' + p);
Run Code Online (Sandbox Code Playgroud)

你会看见:

n = 9007199254740991,m = 9007199254740992,p = 9007199254740992

您的数字表示不会包裹,而是会降低准确性.


请注意,这个"脱落准确性的行为不是唯一的JavaScript,这是你从浮点数据类型的期望.另一个.NET示例:

using System;

public class Program
{
    public static void Main()
    {
        float n = 16777214; // 2^24 - 2
        for(int i = 0; i < 4; ++i) 
        {
            Console.WriteLine(string.Format("n = {0}", n.ToString("0")));
            Console.WriteLine("(n+1) - n = {0}", (n+1)-n);
            n = n + 1;                
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这将输出:

n = 16777210
(n+1) - n = 1
n = 16777220
(n+1) - n = 1
n = 16777220
(n+1) - n = 0
n = 16777220
(n+1) - n = 0
Run Code Online (Sandbox Code Playgroud)