这是由语言定义的吗?是否有定义的最大值?在不同的浏览器中是否有所不同?
1n << 10000n
是一个非常非常大的整数,不会失去任何精度,也不需要任何依赖项(不用说,甚至没有接近极限)。
这是由语言定义的吗?是否有定义的最大值?在不同的浏览器中是否有所不同?
1n << 10000n
是一个非常非常大的整数,不会失去任何精度,也不需要任何依赖项(不用说,甚至没有接近极限)。
Answers:
JavaScript有两种数字类型:Number
和BigInt
。
最常用的数字类型Number
为64位浮点IEEE 754数字。
该类型的最大精确整数值为Number.MAX_SAFE_INTEGER
,即:
从一个角度来看:一个四兆字节是PB(或一千TB)。
在本文中,“安全”是指能够准确表示整数并正确比较它们的能力。
请注意,所有大小不大于2 53的正整数和负整数都可以在该
Number
类型中表示(实际上,整数0具有+0和-0两种表示形式)。
为了安全地使用大于此值的整数,您需要使用BigInt
,没有上限。
请注意,按位运算符和移位运算符对32位整数进行运算,因此在这种情况下,最大安全整数为2 31 -1或2,147,483,647。
const log = console.log
var x = 9007199254740992
var y = -x
log(x == x + 1) // true !
log(y == y - 1) // also true !
// Arithmetic operators work, but bitwise/shifts only operate on int32:
log(x / 2) // 4503599627370496
log(x >> 1) // 0
log(x | 1) // 1
关于数字9,007,199,254,740,992的技术说明:该值有一个精确的IEEE-754表示形式,您可以从变量中分配和读取该值,因此对于在小于或等于整数的整数域中非常仔细选择的应用程序此值,您可以将其视为最大值。
在一般情况下,您必须将此IEEE-754值视为不精确,因为它是编码逻辑值9,007,199,254,740,992还是9,007,199,254,740,993都是模棱两可的。
4294967295 === Math.pow(2,32) - 1;
> = ES6:
Number.MIN_SAFE_INTEGER;
Number.MAX_SAFE_INTEGER;
<= ES5
从参考:
Number.MAX_VALUE;
Number.MIN_VALUE;
Number.MIN_VALUE
是最小的正数。该至少值(即小于其他东西)是可能-Number.MAX_VALUE
。
Number.MIN_SAFE_INTEGER
和Number.MAX_SAFE_INTEGER
它是2 53 == 9 007 199 254 740 740992。这是因为Number
s作为浮点存储在52位尾数中。
最小值是-2 53。
这使一些有趣的事情发生了
Math.pow(2, 53) == Math.pow(2, 53) + 1
>> true
而且也可能很危险:)
var MAX_INT = Math.pow(2, 53); // 9 007 199 254 740 992
for (var i = MAX_INT; i < MAX_INT + 2; ++i) {
// infinite loop
}
进一步阅读:http : //blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html
i += 1000000000
在JavaScript中,有一个名为的数字Infinity
。
例子:
(Infinity>100)
=> true
// Also worth noting
Infinity - 1 == Infinity
=> true
Math.pow(2,1024) === Infinity
=> true
对于有关此主题的某些问题,这可能就足够了。
min
当您寻找最小值时,足以初始化一个变量。
Infinity - 1 === Infinity
1 - Infinity === -Infinity
Jimmy的答案正确地将连续的JavaScript整数频谱表示为-9007199254740992到9007199254740992(包括9007199254740993(很抱歉,您可能认为您是9007199254740993,但您错了! 在jsfiddle中或以下的演示)。
console.log(9007199254740993);
但是,没有以编程方式找到/证明这一问题的答案(除了在他的答案中提到的将在28.56 年内完成的CoolAJ86之外;),所以这是一种更有效的方法(确切地说,它更有效大约28.559999999968312年:),以及测试小提琴:
/**
* Checks if adding/subtracting one to/from a number yields the correct result.
*
* @param number The number to test
* @return true if you can add/subtract 1, false otherwise.
*/
var canAddSubtractOneFromNumber = function(number) {
var numMinusOne = number - 1;
var numPlusOne = number + 1;
return ((number - numMinusOne) === 1) && ((number - numPlusOne) === -1);
}
//Find the highest number
var highestNumber = 3; //Start with an integer 1 or higher
//Get a number higher than the valid integer range
while (canAddSubtractOneFromNumber(highestNumber)) {
highestNumber *= 2;
}
//Find the lowest number you can't add/subtract 1 from
var numToSubtract = highestNumber / 4;
while (numToSubtract >= 1) {
while (!canAddSubtractOneFromNumber(highestNumber - numToSubtract)) {
highestNumber = highestNumber - numToSubtract;
}
numToSubtract /= 2;
}
//And there was much rejoicing. Yay.
console.log('HighestNumber = ' + highestNumber);
x++
会在增量发生之前为您提供x的值,因此很可能可以解释差异。如果您希望表达式的计算结果与x的最终值相同,则应将其更改为++x
。
var MAX_INT = 4294967295;
我以为我会很聪明,x + 1 === x
并能以更务实的方式找到价值所在。
我的机器每秒只能计数1000万左右...因此,我将在28.56年后给出确切的答案。
如果你不能等那么久,我愿意打赌
9007199254740992 === Math.pow(2, 53) + 1
足够证明4294967295
这样Math.pow(2,32) - 1
做,以免发生移位的预期问题发现x + 1 === x
:
(function () {
"use strict";
var x = 0
, start = new Date().valueOf()
;
while (x + 1 != x) {
if (!(x % 10000000)) {
console.log(x);
}
x += 1
}
console.log(x, new Date().valueOf() - start);
}());
简短的答案是“取决于情况”。
如果您在任何地方使用按位运算符(或如果您引用的是数组的长度),则范围为:
未签名: 0…(-1>>>0)
签: (-(-1>>>1)-1)…(-1>>>1)
(碰巧将按位运算符和数组的最大长度限制为32位整数。)
如果您不使用按位运算符或使用数组长度:
签: (-Math.pow(2,53))…(+Math.pow(2,53))
这些限制是由“数字”类型的内部表示所施加的,该类型通常对应于IEEE 754双精度浮点表示。(请注意,与典型的有符号整数不同,由于内部表示的特性,负极限的幅度与正极限的幅度相同,实际上包括负数 0!)
ECMAScript 6:
Number.MAX_SAFE_INTEGER = Math.pow(2, 53)-1;
Number.MIN_SAFE_INTEGER = -Number.MAX_SAFE_INTEGER;
MAX_SAFE_INTEGER
通过向后工作在所有浏览器中进行计算是否可靠?您应该前进吗?即Number.MAX_SAFE_INTEGER = 2 *(Math.pow(2,52)-1)+ 1;
Math.pow(2, 53)-1
一个安全的操作?它比最大安全整数大一。
从早期的许多答案都显示出结果true
的9007199254740992 === 9007199254740992 + 1
验证9 007 199 254 740 991是最大的,安全的整数。
如果我们继续进行积累怎么办:
input: 9007199254740992 + 1 output: 9007199254740992 // expected: 9007199254740993
input: 9007199254740992 + 2 output: 9007199254740994 // expected: 9007199254740994
input: 9007199254740992 + 3 output: 9007199254740996 // expected: 9007199254740995
input: 9007199254740992 + 4 output: 9007199254740996 // expected: 9007199254740996
我们发现,在大于9 007 199 254 740 992的数字中,只有偶数是可表示的。
这是解释双精度64位二进制格式如何在其上工作的入口。让我们看看如何 9 007 199 254 740 992使用这种二进制格式保存(表示)。
使用简短的版本从4503599627370496进行演示:
1 . 0000 ---- 0000 * 2^52 => 1 0000 ---- 0000.
|-- 52 bits --| |exponent part| |-- 52 bits --|
在箭头的左侧,我们有位值1和一个相邻的小数点,然后乘以2^52
,我们将小数点右移52步,然后到最后。现在我们以二进制形式获得4503599627370496。
现在,我们开始将1累加到该值,直到所有位都设置为1,即十进制等于9007199254254740991。
1 . 0000 ---- 0000 * 2^52 => 1 0000 ---- 0000.
(+1)
1 . 0000 ---- 0001 * 2^52 => 1 0000 ---- 0001.
(+1)
1 . 0000 ---- 0010 * 2^52 => 1 0000 ---- 0010.
(+1)
.
.
.
1 . 1111 ---- 1111 * 2^52 => 1 1111 ---- 1111.
现在,由于采用双精度64位二进制格式,它严格分配52位用于小数,因此再也没有位可用于加一,因此,我们要做的就是将所有位都设置回0,然后操作指数部分:
|--> This bit is implicit and persistent.
|
1 . 1111 ---- 1111 * 2^52 => 1 1111 ---- 1111.
|-- 52 bits --| |-- 52 bits --|
(+1)
(radix point has no way to go)
1 . 0000 ---- 0000 * 2^52 * 2 => 1 0000 ---- 0000. * 2
|-- 52 bits --| |-- 52 bits --|
=> 1 . 0000 ---- 0000 * 2^53
|-- 52 bits --|
现在我们得到 9 007 199 254 740 740 992,数字大于它,格式可以容纳分数的2倍,这意味着分数部分上每加1实际上等于2加法,这就是为什么double当数字大于9007 199 254 740 740 992时,精度64位二进制格式不能包含奇数:
(consume 2^52 to move radix point to the end)
1 . 0000 ---- 0001 * 2^53 => 1 0000 ---- 0001. * 2
|-- 52 bits --| |-- 52 bits --|
因此,当数字大于9 007 199 254 740 992 * 2 = 18 014 398 509 481 481 984时,只能保留分数的4倍:
input: 18014398509481984 + 1 output: 18014398509481984 // expected: 18014398509481985
input: 18014398509481984 + 2 output: 18014398509481984 // expected: 18014398509481986
input: 18014398509481984 + 3 output: 18014398509481984 // expected: 18014398509481987
input: 18014398509481984 + 4 output: 18014398509481988 // expected: 18014398509481988
如何[之间号2 251 799 813 685 248,4 503 599 627 370 496)?
1 . 0000 ---- 0001 * 2^51 => 1 0000 ---- 000.1
|-- 52 bits --| |-- 52 bits --|
小数点后的位值1恰好是2 ^ -1。(= 1/2,= 0.5)因此,当数字小于4 503 599 627 370 496(2 ^ 52)时,可用一位表示整数的1/2倍:
input: 4503599627370495.5 output: 4503599627370495.5
input: 4503599627370495.75 output: 4503599627370495.5
少于2251799813685248(2 ^ 51)
input: 2251799813685246.75 output: 2251799813685246.8 // expected: 2251799813685246.75
input: 2251799813685246.25 output: 2251799813685246.2 // expected: 2251799813685246.25
input: 2251799813685246.5 output: 2251799813685246.5
// If the digits exceed 17, JavaScript round it to print it.
//, but the value is held correctly:
input: 2251799813685246.25.toString(2)
output: "111111111111111111111111111111111111111111111111110.01"
input: 2251799813685246.75.toString(2)
output: "111111111111111111111111111111111111111111111111110.11"
input: 2251799813685246.78.toString(2)
output: "111111111111111111111111111111111111111111111111110.11"
指数部分的可用范围是多少?格式为此分配11位。Wiki的完整格式:(有关更多详细信息,请转到此处)
因此,要使指数部分为2 ^ 52,我们确实需要设置e = 1075。
其他人可能已经给出了通用答案,但是我认为提供一种快速的方法来确定它是一个好主意:
for (var x = 2; x + 1 !== x; x *= 2);
console.log(x);
在Chrome 30中不到一毫秒的时间内,我得到了9007199254740992。
它将测试2的幂,以发现“加” 1时哪个等于自己。
尝试:
maxInt = -1 >>> 1
在Firefox 3.6中为2 ^ 31-1。
^
指提高权力。在Javascript控制台中,^
是XOR而不是引发
101
,2是010
。现在,如果你位异或他们,你会得到5(101) ^ 2(010) = 7(111)
READ这一点,如果你困惑 这里正在讨论是Math.pow()
不是^
运营商
在撰写本文时,JavaScript正在接收一种新的数据类型:BigInt
。这是TC39提案的第4阶段,将包含在EcmaScript 2020中。BigInt
适用于Chrome 67 +,FireFox 68 +,Opera 54和Node 10.4.0。它正在Safari等系统中进行。它引入了带有“ n”后缀的数字文字,并允许任意精度:
var a = 123456789012345678901012345678901n;
当然,当这样的数字(可能是无意间)强制转换为数字数据类型时,精度仍然会丢失。
并且,显然,由于有限的存储器而总是存在精度限制,并且为了分配必要的存储器并且对如此大的数字执行算术在时间方面存在成本。
例如,生成具有十万个十进制数字的数字将在完成之前花费明显的延迟:
console.log(BigInt("1".padEnd(100000,"0")) + 1n)
...但是有效。
我使用公式X-(X + 1)=-1进行了简单测试,并且XI可以在Safari,Opera和Firefox上运行(在OS X上测试过)的最大值是9e15。这是我用于测试的代码:
javascript: alert(9e15-(9e15+1));
9000000000000000
有1个重要数字。在“ 9007199254740992”中,有15个有效数字。
9000000000000000
-是1
SF。其中90*10^14
有2(sigfigscalculator.appspot.com)mathsfirst.massey.ac.nz/Algebra/Decimals/SigFig.htm(底部)
该
MAX_SAFE_INTEGER
常数的值为9007199254740991
(9,007,199,254,740,991或〜9万亿)。该数字背后的原因是,JavaScript使用IEEE 754中指定的双精度浮点格式数字,并且只能安全地表示介于和之间的数字。-(2^53 - 1)
2^53 - 1
。在此上下文中,安全是指能够精确表示整数并正确比较它们的能力。例如,
Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2
将评估为true,这在数学上是不正确的。请参见Number.isSafeInteger()更多信息,。因为
MAX_SAFE_INTEGER
是Number的静态属性,所以您始终将其用作Number.MAX_SAFE_INTEGER
,而不是用作创建的Number对象的属性。
在Google Chrome内置的javascript中,您可以先转到2 ^ 1024,然后再将数字称为无穷大。
在JavaScript中,数字表示为 2^53 - 1
。
但是,Bitwise operation
是根据计算的32 bits ( 4 bytes )
,这意味着如果您超过32位移位,您将开始丢失位。
Node.js和Google Chrome似乎都使用1024位浮点值,因此:
Number.MAX_VALUE = 1.7976931348623157e+308
2^53
之所以称为,是MAX_SAFE_INT
因为在该点之上,值以近似的方式变为近似值。