Math
的新特性 Number
属性Math
方法Number.parseInt()
和新的整数字面量Number
属性Number.EPSILON
Number.isInteger(number)
Math
功能您现在可以使用二进制和八进制表示法指定整数
Number
属性 全局对象 Number
获得了一些新的属性
Number.EPSILON
用于比较浮点数时考虑舍入误差的容差。Number.isInteger(num)
检查 num
是否为整数(没有小数部分的数字)
Number.isSafeInteger(number)
Number.MIN_SAFE_INTEGER
Number.MAX_SAFE_INTEGER
Number.isNaN(num)
检查 num
是否为 NaN
值。与全局函数 isNaN()
相比,它不会将其参数强制转换为数字,因此对于非数字更安全
Number
的另外三个方法与其同名的全局函数基本相同:Number.isFinite
、Number.parseFloat
、Number.parseInt
。Math
方法 全局对象 Math
具有用于数值、三角函数和位运算的新方法。让我们看四个例子。
Math.sign()
返回数字的符号
Math.trunc()
删除数字的小数部分
Math.log10()
计算以 10 为底的对数
Math.hypot()
计算其参数平方和的平方根(勾股定理)
ECMAScript 5 已经具有十六进制整数的字面量
ECMAScript 6 带来了两种新的整数字面量
0b
或 0B
0o
或 0O
(即零后跟大写字母 O;第一种变体更安全)
请记住,Number
方法 toString(radix)
可用于查看以 10 以外的进制表示的数字
(双点是必需的,这样属性访问的点就不会与小数点混淆。)
在 Node.js 文件系统模块 中,有几个函数具有参数 mode
。其值用于通过从 Unix 继承的编码来指定文件权限
这意味着权限可以用 9 位表示(3 类用户,每类 3 个权限)
用户 | 组 | 所有 | |
---|---|---|---|
权限 | r, w, x | r, w, x | r, w, x |
位 | 8, 7, 6 | 5, 4, 3 | 2, 1, 0 |
单个用户类别的权限存储在 3 位中
位 | 权限 | 八进制数字 |
---|---|---|
000 | ––– | 0 |
001 | ––x | 1 |
010 | –w– | 2 |
011 | –wx | 3 |
100 | r–– | 4 |
101 | r–x | 5 |
110 | rw– | 6 |
111 | rwx | 7 |
这意味着八进制数是所有权限的紧凑表示形式,您只需要 3 位数字,每类用户一位数字。两个例子
Number.parseInt()
和新的整数字面量 Number.parseInt()
(与全局函数 parseInt()
相同)具有以下签名
Number.parseInt()
:十六进制数字字面量 如果满足以下条件,则 Number.parseInt()
为十六进制字面量表示法提供特殊支持 – 如果
radix
缺失或为 0,则删除 string
的前缀 0x
(或 0X
)。然后将 radix
设置为 16。通常,您永远不应省略 radix
。radix
为 16。例如
在所有其他情况下,仅解析数字直到第一个非数字字符
Number.parseInt()
:二进制和八进制数字字面量 但是,Number.parseInt()
不支持二进制或八进制字面量!
如果要解析这类字面量,则需要使用 Number()
只要没有特殊前缀并提供了参数 radix
,Number.parseInt()
就可以很好地处理具有不同进制的数字
Number
属性 本节介绍构造函数 Number
在 ECMAScript 6 中获得的新属性。
四个与数字相关的函数已经作为全局函数可用,并已作为方法添加到 Number
中:isFinite
和 isNaN
、parseFloat
和 parseInt
。它们的工作方式与其全局函数几乎相同,但 isFinite
和 isNaN
不再将其参数强制转换为数字,这对 isNaN
尤为重要。以下小节将解释所有详细信息。
Number.isFinite(number)
Number.isFinite(number)
确定 number
是否为实际数字(既不是 Infinity
也不是 -Infinity
也不是 NaN
)
此方法的优点是它不会将其参数强制转换为数字(而全局函数会)
Number.isNaN(number)
Number.isNaN(number)
检查 number
是否为 NaN
值。
ES5 中进行此检查的一种方法是通过 !==
更具描述性的方法是通过全局函数 isNaN()
但是,此函数会将非数字强制转换为数字,如果结果为 NaN
,则返回 true
(这通常不是您想要的)
新方法 Number.isNaN()
不会出现此问题,因为它不会将其参数强制转换为数字
Number.parseFloat
和 Number.parseInt
以下两种方法的工作方式与其同名的全局函数完全相同。为了完整起见,将它们添加到了 Number
中;现在所有与数字相关的函数都可以在那里使用。
Number.EPSILON
特别是在使用小数时,舍入误差在 JavaScript 中可能会成为一个问题3。例如,0.1 和 0.2 不能精确表示,如果您将它们相加并与 0.3(也不能精确表示)进行比较,您会注意到这一点。
Number.EPSILON
指定了比较浮点数时的合理误差范围。它提供了一种更好的比较浮点值的方法,如以下函数所示。
Number.isInteger(number)
JavaScript 只有浮点数(双精度)。因此,整数只是没有小数部分的浮点数。
如果 number
是数字并且没有小数部分,则 Number.isInteger(number)
返回 true
。
JavaScript 数字只有足够的存储空间来表示 53 位有符号整数。也就是说,范围为 −253 < *i* < 253 的整数 *i* 是*安全*的。稍后将解释这到底意味着什么。以下属性有助于确定 JavaScript 整数是否安全
Number.isSafeInteger(number)
Number.MIN_SAFE_INTEGER
Number.MAX_SAFE_INTEGER
*安全整数*的概念围绕着如何在 JavaScript 中表示数学整数。在 (−253, 253) 范围内(不包括上下限),JavaScript 整数是*安全*的:它们与它们表示的数学整数之间存在一对一的映射。
超出此范围,JavaScript 整数是*不安全*的:两个或多个数学整数表示为同一个 JavaScript 整数。例如,从 253 开始,JavaScript 只能表示每隔一个数学整数
因此,安全的 JavaScript 整数是明确表示单个数学整数的整数。
Number
属性 指定安全整数上下限的两个静态 Number
属性可以定义如下
Number.isSafeInteger()
确定 JavaScript 数字是否是安全整数,可以定义如下
对于给定值 n
,此函数首先检查 n
是否为数字和整数。如果两项检查都成功,则如果 n
大于或等于 MIN_SAFE_INTEGER
且小于或等于 MAX_SAFE_INTEGER
,则 n
是安全的。
我们如何确保使用整数的计算结果是正确的?例如,以下结果显然是不正确的
我们有两个安全的操作数,但结果不安全
以下结果也不正确
这次,结果是安全的,但其中一个操作数不是
因此,仅当所有操作数和结果都是安全的情况下,应用整数运算符 op
的结果才能保证是正确的。更正式地说
意味着 a op b
是正确的结果。
Math
功能 全局对象 Math
在 ECMAScript 6 中有几个新方法。
Math.sign(x)
Math.sign(x)
返回
-1
如果 x
是负数(包括 -Infinity
)。0
如果 x
是零4。+1
如果 x
是正数(包括 Infinity
)。NaN
如果 x
是 NaN
或不是数字。例子
Math.trunc(x)
Math.trunc(x)
去除 x
的小数部分。 补充了其他舍入方法 Math.floor()
、Math.ceil()
和 Math.round()
。
您可以像这样实现 Math.trunc()
Math.cbrt(x)
Math.cbrt(x)
返回 x
的立方根 (∛x)。
如果一个小数位于零之后,则可以更精确地表示它。我将用十进制小数来演示这一点(JavaScript 的数字在内部以 2 为基数存储,但同样的推理也适用)。
以 10 为底的浮点数在内部表示为 *尾数* × 10指数。*尾数* 在小数点前有一位数字,*指数* 根据需要“移动”小数点。这意味着,如果将一个小数转换为内部表示形式,则点前的零会导致尾数小于点前的一。例如
就精度而言,这里重要的量是用有效数字衡量的尾数的容量。这就是为什么 (A) 比 (B) 提供更高的精度。
此外,JavaScript 以更高的精度表示接近零的数字(例如,小数)。
Math.expm1(x)
Math.expm1(x)
返回 Math.exp(x)-1
。Math.log1p()
的反函数。
因此,每当 Math.exp()
的结果接近 1 时,此方法都提供更高的精度。您可以在以下交互中看到两者之间的区别
前者是更好的结果,您可以使用任意精度浮点数(“bigfloats”)的库(例如 decimal.js)来验证
Math.log1p(x)
Math.log1p(x)
返回 Math.log(1 + x)
。Math.expm1()
的反函数。
因此,此方法允许您以更高的精度指定接近 1 的参数。以下示例演示了原因。
以下两次调用 log()
产生相同的结果
相反,log1p()
产生不同的结果
Math.log1p()
精度更高的原因是 1 + 1e-16
的正确结果比 1e-16
具有更多有效数字
Math.log2(x)
Math.log2(x)
计算以 2 为底的对数。
Math.log10(x)
Math.log10(x)
计算以 10 为底的对数。
Emscripten 开创了一种后来被 asm.js 采用的编码风格:虚拟机(想想字节码)的操作在 JavaScript 的静态子集中表达。该子集可以由 JavaScript 引擎有效执行:如果它是 C++ 编译的结果,则其运行速度约为本机速度的 70%。
以下 Math
方法主要是为了支持 asm.js 和类似的编译策略而添加的,它们对其他应用程序没有那么有用。
Math.fround(x)
Math.fround(x)
将 x
舍入为 32 位浮点值 (float
)。由 asm.js 使用,用于告诉引擎在内部使用 float
值。
Math.imul(x, y)
Math.imul(x, y)
将两个 32 位整数 x
和 y
相乘,并返回结果的低 32 位。这是唯一不能通过使用 JavaScript 运算符并将结果强制转换回 32 位来模拟的 32 位基本数学运算。例如,idiv
可以实现如下
相反,将两个大的 32 位整数相乘可能会产生一个非常大的双精度数,从而丢失低位。
Math.clz32(x)
x
中的前导零位数。
为什么这很有趣?引用 Miro Samek 的“快速、确定和可移植的计数前导零”
计算整数中的前导零是许多 DSP 算法中的关键操作,例如声音或视频处理中样本的归一化,以及实时调度程序中快速找到准备运行的最高优先级任务。
Math.sinh(x)
x
的双曲正弦。Math.cosh(x)
x
的双曲余弦。Math.tanh(x)
x
的双曲正切。Math.asinh(x)
x
的反双曲正弦。Math.acosh(x)
x
的反双曲余弦。Math.atanh(x)
x
的反双曲正切。Math.hypot(...values)
JavaScript 的整数范围为 53 位。每当需要 64 位整数时,这都是一个问题。例如:在其 JSON API 中,当推文 ID 过大时,Twitter 不得不从整数切换到字符串。
目前,解决此限制的唯一方法是使用更高精度数字(bigint 或 bigfloat)的库。一个这样的库是 decimal.js。
在 JavaScript 中支持更大整数的计划已经存在,但可能需要一段时间才能实现。