JavaScript中的数值

JavaScript中的主要数值类型是Number类型,用于表示整数和近似的实数。JavaScript采用了由IEEE 754标准定义的64位浮点格式来表示数值。这意味着JavaScript可以表示最大整数±1.797 693 134 862 315 7 × 10^308和最小整数±5 × 10^-324。
JavaScript中的这种数值格式允许我们准确表示介于-9,007,199,254,740,992(-2^53)和9,007,199,254,740,992(2^53)之间的所有整数。如果您的值超出此范围,可能会在最低有效位处丧失一些精度。
当一个数值直接出现在JavaScript程序中时,它被称为“数值字面量”。请注意,任何数值字面量都可以在前面加上减号(-)以使值为负。
1. 整数字面量.
在JavaScript程序中,十进制整数可以直接写为数字序列。例如:
除了十进制整数字面量,JavaScript还支持十六进制(基数16)的值。十六进制字面量以0x或0X开头,后面跟着十六进制数字字符串。十六进制数字由数字0到9和字母a(或A)到f(或F)组成,其中a到f代表10到15。以下是十六进制整数字面量的示例:
在ES6及更高版本中,您还可以使用前缀0b和0o(或0B和0O)来表示二进制(基数2)或八进制(基数8)的整数:
(程序员的软技能:ke.qq.com/course/6034346)
2. 浮点数字面量.
浮点数字面量可以包含小数点,并遵循实数的传统语法。实数由数字的整数部分、小数点和数字的小数部分组成。
浮点数字面量还可以使用指数表示法,其中实数后跟字母e(或E),一个可选的加号或减号,以及一个整数指数。这种表示法表示实数乘以10的指数次幂。
更简洁的语法形式为:
例如:
您可以使用下划线来分隔数值字面量的各个部分,这是一种已进入标准化后期并受到所有主要浏览器和Node实现支持的功能:
(程序员的软技能:ke.qq.com/course/6034346)
3. JavaScript中的算术运算。
JavaScript程序使用语言提供的算术运算符来操作数值。这些运算符包括加法+、减法-、乘法*、除法/和取模(除法后的余数)%。ES2016引入了指数运算符**。
除了这些基本的算术运算符,JavaScript还通过Math对象提供了一组函数和常量,以支持更复杂的数学计算:
ES6在Math对象上引入了一组新的函数:
在JavaScript中,算术不会在遇到溢出、下溢或除以零时抛出错误。当数值操作的结果超出可表示范围(溢出)时,结果是特殊的无限值Infinity。类似地,当负数的绝对值超出负数的可表示范围(下溢)时,结果为负无穷-Infinity。这两个无限值的行为符合预期:涉及加法、减法、乘法或除法的任何算术运算都会导致无限值(尽管符号可能会改变)。
当数值操作的结果接近零但仍大于最小可表示数时,发生下溢。在这种情况下,JavaScript返回0。如果下溢发生在倒数的情况下,JavaScript返回一个称为“负零”的特殊值。这个值与普通零几乎无法区分,对于JavaScript程序员来说很少会引起关注。
在JavaScript中,除以零不是错误;它只会导致无限或负无穷。然而,有一个例外:将0除以0会得到一个称为“非数”(NaN)的特殊值。此外,类似无限除以无限、负数的平方根或在算术运算中使用NaN作为操作数等操作都会产生NaN作为结果。
JavaScript预定义了全局常量Infinity和NaN,分别对应正无穷大和非数。这些值也可以通过Number对象的属性访问:
ES6在Number对象上引入了以下属性:
在JavaScript中,NaN具有一种不寻常的特性:它既不等于任何值,也不等于自身。这意味着您不能通过使用x === NaN比较来确定变量x是否为NaN。相反,您必须使用x != x或Number.isNaN(x)来测试NaN。这两个表达式只在x与全局常量NaN具有相同值时才返回true。
全局函数isNaN()与Number.isNaN()类似。当参数为NaN或参数为不能转换为数字的非数值时,它返回true。相关的函数Number.isFinite()在参数不是NaN、Infinity或-Infinity时返回true。全局函数isFinite()在参数为有限数或可转换为有限数的值时返回true。
负零具有稍微不寻常的行为。它被认为等于正零(即使在JavaScript中使用严格相等比较),这意味着除了作为除数的角色外,很难区分这两个值:
(程序员的软技能:ke.qq.com/course/6034346)
4. 二进制浮点数和舍入误差。
实数是无限多的,但JavaScript的浮点数格式只能表示其中的有限子集(确切地说,它可以表示多达18,437,736,874,454,810,627个不同的值)。这意味着当您在JavaScript中使用实数时,您操作的数值通常是实际值的近似值。
JavaScript(以及所有现代编程语言)使用IEEE-754浮点表示,这是一种二进制表示。这种表示可以准确地表示像1/2、1/8和1/1024这样的分数。然而,我们常用的最常见的分数(尤其是在财务计算中)是十进制分数,如1/10、1/100等。二进制浮点表示无法精确表示甚至简单的数字如0.1。
虽然JavaScript的数值具有足够的精度,可以非常接近地近似0.1,但不能完全表示它。这可能会导致问题,如以下代码所示:
由于舍入误差,近似值0.3和0.2之间的差异不等于近似值0.2和0.1之间的差异。这不是JavaScript特定的问题;这是所有使用二进制浮点数的编程语言的常见问题。还要注意,上述代码中的x和y的值非常接近,它们非常接近正确的值。计算出的值对于大多数目的来说都是完全合适的,但不建议尝试比较它们的精确相等性。
如果近似浮点值在您的程序中造成问题,您可以考虑使用等价的整数。例如,在处理与货币相关的计算时,您可以使用以分为单位的整数表示,而不是以美元的一部分为单位的分数。
(程序员的软技能:ke.qq.com/course/6034346)
5. 用BigInt表示任意精度整数。
在ES2020中,JavaScript引入了一种新的数字类型,称为BigInt。截至2020年初,Chrome、Firefox、Edge和Node.js已经实现了这种类型,Safari也在进行相关工作。正如名称所示,BigInt值是整数。添加此类型的主要动机是为了表示64位整数,这对于与许多其他语言和API的兼容性至关重要。然而,BigInt值可以具有数千甚至数百万位的数字,以满足大数值的需求(尽管BigInt实现不适合用于加密,因为它们不考虑防御定时攻击)。
BigInt字面量由一系列数字后跟小写字母"n"组成。默认情况下,基数为10,但您可以使用前缀0b、0o和0x分别表示二进制、八进制和十六进制的BigInt:
您可以使用BigInt()函数将常规JavaScript数字或字符串转换为BigInt值:
与BigInt值的算术操作类似于常规JavaScript数字操作,除法除去余数并朝向零四舍五入:
尽管标准的+、-、*、/、%和**运算符适用于BigInt,但您不能将BigInt操作数与常规数字操作数混合使用。乍看起来,这个规则可能有点奇怪,但实际上是合理的。如果一个数值类型比另一个更通用,那么定义混合操作数计算并返回更通用的类型是很容易的。然而,在这种情况下,这两种类型都不比另一种更通用:BigInt可以表示非常大的值,使其在常规数值类型之间更通用。但是BigInt只能表示整数,这使得常规JavaScript数值类型在这个方面更通用。这种困境无法解决,因此在使用算术运算符时,JavaScript简单地禁止混合使用这两种操作数类型。
另一方面,比较运算符允许混合操作数类型:
位运算符通常可以与BigInt操作数一起使用。然而,Math对象的函数中没有一个接受BigInt操作数。
(程序员的软技能:ke.qq.com/course/6034346)
6. 日期和时间。
JavaScript提供了一个简单的Date类,用于表示和操作与日期和时间有关的数据。JavaScript的Date是一个对象,但它也具有一个数值表示,称为时间戳,它是自1970年1月1日以来的毫秒数:
(程序员的软技能:ke.qq.com/course/6034346)