基本概念
js 内部,整数和浮点数都是以64位浮点数形式储存,在js底层根本没有整数,所以在js定义数值时不会区分整数和浮点数(某些需要整数进行的运算,js会把相应数值转为32整数再进行运算)
js的浮点数是使用IEEE 754标准,整数运算最大精度是[-253到253],也就是在这个范围的数值运算都是精确的,但是根据标准js能表示的数值范围是(21024到2-1023),超出这个范围的数无法表示,正向溢出的值用Infinity表示,负向溢出用0表示
Number.MAX_VALUE; 最大值
Number.MIN_VALUE; 最小值
ES6 引入了Number.MAX_SAFE_INTEGER 和 Number.MIN_SAFE_INTEGER,用来表示精度范围的上下限
Number.MAX_SAFE_INTEGER === Math.pow(2, 53) - 1; // true
Number.MIN_SAFE_INTEGER === -(Math.pow(2, 53) - 1); // true
数值的表示方法
十进制: 35 无任何前缀
十六进制: 0x23 以0x开头
八进制: 0o43 以0o开头(es6废除以0开头表示8进制的写法)
二进制: 0b100011 以0b开头
特殊值
正零(0) 和负零(-0) 除了当除数外(一个是Infinity,一个-Infinity),两个0完全一致
NaN 非数字(这个是特殊数字,数据类型还是Number),主要用于解析成数字出错或者运算出错的场景,主要特性:
- NaN不等于任何值,包括它本身
- NaN在布尔运算时被当作false
- NaN与任何数(包括它自己)的运算,得到的都是NaN
Infinity 无穷,与数学概念上的无穷概念一致,主要特性:
- Infinity大于一切数值(除了NaN),-Infinity小于一切数值(除了NaN),Infinity与NaN比较,总是返回false
- Infinity进行四则运算时和无穷数学运算一致
// Infinity的四则运算,符合无穷的数学计算规则。
5 * Infinity // Infinity
5 - Infinity // -Infinity
Infinity / 5 // Infinity
5 / Infinity // 0
0 * Infinity // NaN 0乘以Infinity,返回NaN
0 / Infinity // 0 0除以Infinity,返回0
Infinity / 0 // Infinity Infinity除以0,返回Infinity
// Infinity加上或乘以Infinity,返回的还是Infinity。
Infinity + Infinity // Infinity
Infinity * Infinity // Infinity
// Infinity减去或除以Infinity,得到NaN。
Infinity - Infinity // NaN
Infinity / Infinity // NaN
// Infinity与null计算时,null会转成0,等同于与0的计算。
null * Infinity // NaN
null / Infinity // 0
Infinity / null // Infinity
// Infinity与undefined计算,返回的都是NaN。
undefined + Infinity // NaN
undefined - Infinity // NaN
undefined * Infinity // NaN
undefined / Infinity // NaN
Infinity / undefined // NaN
相关方法
parseInt
用于将字符串转为整数
parseInt('123'); // 123
parseInt(' 81'); // 81 有空格会自动去除
字符串转为整数的时候,是一个个字符依次转换,如果遇到不能转为数字的字符,就不再进行下去,返回已经转好的部分
parseInt('8a'); // 8
parseInt('12**'); // 12
科学计数法的字符串也只会当做普通字符串处理
parseInt('314e-2'); // 314
parseInt的参数不是字符串,则会先转为字符串再转换
parseInt(true - 0 + '0') // 10, true - 0 + '0' : '10'
// 如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN
parseInt('.2'); // NaN
parseInt('+0.2'); // 0
// 如果是其他进制的数字,parseInt只会处理16进制的数字,其他进制不处理
parseInt('0x23'); // 35, 35的十六进制形式
parseInt('0o43'); // 0, 35的八进制形式
parseInt('0b100011'); // 0, 35的二进制形式
parseInt本意是将字符串转为数字,但是如果其中要转换的是其他数据类型会先转成字符串再转为数字。其他数据类型都比较好理解,按照把其值转为字符的形式,再转为数字的形式就能理解其中的转换
parseInt(true); // true -> 'true' -> NaN
paresInt([]); // [] -> '' -> NaN
parseInt([1, 2, 3]); // [1, 2, 3] -> "1,2,3" -> 1
parseInt({}); // {} -> "[object Object]" -> NaN
parseInt(function a () {}); // function a () {} -> "function a () {}" -> NaN
数字类型的转换会有点不同,主要体现在科学计数法
parseInt(1); // 1 -> '1' -> 1
parseInt(1000000000000000000000); // 1000000000000000000000 -> '1e+21' -> 1
parseInt(0.0000008); // 0.0000008 -> '8e-7' -> 8
如果是其他进制的数字则是会先转成十进制再转成字符,再转成数字
parseInt(0x11); // 0x11 -> 17 -> '17' -> 17
parseInt可以接收第二个参数,用来表示以什么进制转换数字,但是这个转换只会针对相应进制有意义的数字进行依次处理,碰到不合理的数字直接跳过
parseInt('35', 2); // NaN, 3不在2进制中
parseInt('135', 2); // 1, 1在2进制中有意义
parseInt('315', 2); // NaN, 依次处理,第一个数没意义就会直接停止
parseInt('011', 2); // 3, 011按二进制处理,转为数字3
parseInt(011, 2); // 011 -> 9 -> '9' -> NaN
parseFloat
将一个字符串转为浮点数,使用方式和parseInt基本一致
parseFloat('3.14'); // 3.14
如果是科学计算法的字符串会先转换再转成数字,这点和parseInt不同
parseInt('314e-2'); // 314
parseInt('314e-2'); // 3.14
另外如果是数字过大也可以正常转换
parseFloat(1000000000000000000000); // 1e+21
parseInt(1000000000000000000000); // 1
ES6把全局方法parseInt和parseFloat,移植到Number对象上面,行为完全保持不变,其调用可以是Number.parseInt和Number.parseFloat
isNaN
判断一个值是否为NaN
isNaN(NaN); // true
// 如果传入的不是一个数字,会先转为数字再进行比较
isNaN('Hello'); // true
// 判断一个值是否为NaN,可以利用NaN是唯一一个不等于本身的值的特点做判断
NaN === NaN; // false
isFinite
返回一个布尔值,用来检查一个数值是否为有限的(finite),即不是Infinity
// Infinity、-Infinity、NaN和undefined这几个值会返回false
// isFinite对于其他的数值都会返回true(应该是其他数值都能转成数字)
isFinite(undefined); // false
isFinite(null); // true
isFinite(-1); // true
isNaN和isFinite在使用时都会进行类型转换,把非数值类型转为数值,在可以判断,这就会造成某些情况下,使用这些方法做的判断不一定是准确的,所以在ES6中Number对象上新提供了Number.isFinite和Number.isNaN做相关判断,使用方式和isNaN、isFinite一致,但判断却变的更为严谨
isFinite(true); // true, 这个值的判断就会让人有些疑惑,从根本上来说一个布尔型的,不应该是正常数值,判断为true不过是类型进行了转换
Number.isFinite(true); // false,如果参数类型不是数值,Number.isFinite一律返回false,并不会做类型转换
isNaN('Hello'); // true
Number.isNaN('Hello'); // false, 如果参数类型不是NaN,Number.isNaN一律返回false
toExponential
以指数表示法返回该数值字符串表示形式
77.1234.toExponential(); // 7.71234e+1
// 可接收参数用来指定小数点后有几位数字
77.1234.toExponential(2); // 7.71e+1
toFixed
四舍五入为指定小数位数的数字
123.4561.toFixed(); // 123
123.4561.toFixed(1); // 123.5
123.4561.toFixed(1); // 123.456 四舍五入
0.004.toFixed(2); // 0.00
1.23e+5.toFixed(2); // 123000.00
toPrecision
以指定的精度返回该数值对象的字符串表示
5.2134.toPrecision(); // 5.2134
5.2134.toPrecision(2); // 5.2
Number.isInteger
判断数字是否为整数
// 数和浮点数采用的是同样的储存方法,所以 25 和 25.0 被视为同一个值
Number.isInteger(25) // true
Number.isInteger(25.0) // true
Number.isInteger(25.1); // false
如果参数不是数值,Number.isInteger返回false
Number.isInteger('15'); // false
Number.isInteger(null); // false
这个方法存在一定的误差,如果数值有过长的精度,超出了IEEE 754所能表示的精度范围就会进行数值截取,这个小数的精度达到了小数点后16个十进制位,转成二进制位超过了53个二进制位
Number.isInteger(3.0000000000000002); // true, 最后一位2被舍弃,所以结果为true
// 如果一个数值的绝对值小于Number.MIN_VALUE(5E-324),即小于 JavaScript 能够分辨的最小值,会被自动转为 0
Number.isInteger(5E-324); // false
Number.isInteger(5E-325); // true
Number.EPSILON
ES6在Number对象上面,新增一个极小的常量,根据规格,它表示 1 与大于 1 的最小浮点数之间的差,这个值是2-52。误差如果小于这个值,就可以认为已经没有意义了,即不存在误差了,用这个值可以设定最小误差范围,来判断两个值是否相等
Number.EPSILON === Math.pow(2, -52); // true
// 这里设定最小误差范围是2的-50次方
function withinErrorMargin (left, right) {
return Math.abs(left - right) < Number.EPSILON * Math.pow(2, 2);
}
0.1 + 0.2 - 0.3; // 5.551115123125783e-17
0.1 + 0.2 === 0.3 // false
withinErrorMargin(0.1 + 0.2, 0.3) // true
1.1 + 1.3 - 2.4; // 4.440892098500626e-16
1.1 + 1.3 === 2.4 // false
withinErrorMargin(1.1 + 1.3, 2.4) // true
Number.isSafeInteger
来判断一个整数是否在精度范围内(-253, 253)(这是一个开区间,不包括边界值)
Number.isSafeInteger(9007199254740991); // true Math.pow(2, 53) - 1
Number.isSafeInteger(9007199254740992); // false
// 验证运算结果是否落在安全整数的范围内,不止要验证运算结果,同时要验证参与运算的每个值
Number.isSafeInteger(9007199254740993); // false
Number.isSafeInteger(990); // true
Number.isSafeInteger(9007199254740993 - 990); // true
9007199254740993 - 990; // 9007199254740002,这是个错误值,正确值为9007199254740003
Math.abs
返回指定数字的绝对值
Math.acos
返回一个数的反余弦值(单位为弧度)
Math.asin
返回一个数值的反正弦(单位为弧度)
Math.atan
返回一个数值的反正切(以弧度为单位)
Math.atan2
返回其参数比值的反正切值
Math.cbrt
计算一个数的立方根
Math.cbrt(8); // 2
// 非数字先进行转换,转换后为数字则正常处理,无法处理,则返回NaN
Math.cbrt('8'); // 2
Math.cbrt('foo'); // NaN
Math.ceil
向上取整
Math.ceil(.95); // 1
Math.clz32
返回一个数的 32 位无符号整数形式有多少个前导0
// 如果参数是数字,里面的数字会转成2进制,再返回前导有多少个0
Math.clz32(1); // 31 1: 0b1
Math.clz32(2); // 30 2: 0b10
// Math.clz32方法只考虑整数部分,感觉原因可能和带小数点的数字转成2进制时,2进制长度不变有关
Math
Math.clz32(2.1); // 30 2.1: 0b10.000110011...
// 对于空值或其他类型的值,Math.clz32方法会将它们先转为数值,然后再计算
Math.clz32(true); // 31 true -> 1 -> 0b1
Math.cos
返回一个数值的余弦值
Math.exp
函数返回 ex,x 表示参数,e 是欧拉常数(Euler's constant),自然对数的底数
Math.floor
向下取整
Math.fround
将64位双精度浮点数转为32位单精度浮点数(js中整数和浮点数默认是以64位浮点数形式储存)
不过这个方法有什么用,暂时不知...
Math.hypot
返回所有参数的平方和的平方根
Math.hypot(3, 4); // 5 3的平方加上4的平方,再开平方
Math.hypot(3, 4, 5); // 7.0710678118654755
// 如果参数是非数字则进行转换,能转为数字则正常处理,如果不能转为数字则报NaN
Math.hypot(3, '4'); // 5
Math.hypot(3, '4', 'foo'); // NaN
Math.imul
返回两个数以 32 位带符号整数形式相乘的结果,返回的也是一个 32 位的带符号整数
// Math.imul(a, b)与a * b的结果是相同的,该方法等同于(a * b)|0的效果
Math.imul(2, 4) // 8
Math.imul(-1, 8) // -8
Math.imul(-2, -2) // 4
Math.max
返回一组数中的最大值
Math.min
返回零个或更多个数值的最小值
Math.pow
函数返回基数(base)的指数(exponent)次幂,即 baseexponent
Math.random
返回一个浮点, 伪随机数在范围[0,1)
Math.round
函数返回一个数字四舍五入后最接近的整数
Math.sign
判断一个数到底是正数、负数、还是零
Math.sign(2); // 1 表示正数
Math.sign(-2); // -1 表示负数
Math.sign(0); // 0 正0
Math.sign(-0); // -0 负0
// 如果是非数字,可以转为数字的按转换后的数字进行判断
Math.sign(true); // 1
Math.sign('-1'); // -1
// 如果转换后是非数字,则报NaN
Math.sign('foo'); // NaN
Math.sin
函数返回一个数值的正弦值
Math.sqrt
返回一个数的平方根
Math.trunc
用于去除一个数的小数部分,返回整数部分
Math.trunc(4.1); // 4
// 非数字,如果可以转为数字,则处理转换后的值
Math.trunc('123.456') // 123
Math.trunc(true) //1
// 如果不可以转为数字,则报NaN
Math.trunc('foo'); // NaN
对数相关方法
Math.log() 函数返回一个数的自然对数
Math.expm1(x)返回 ex - 1,即Math.exp(x) - 1
Math.log1p(x)方法返回1 + x的自然对数,即Math.log(1 + x)
Math.log10(x)返回以 10 为底的x的对数。如果x小于 0,则返回 NaN
Math.log2(x)返回以 2 为底的x的对数。如果x小于 0,则返回 NaN
双曲函数新增方法
Math.sinh(x) 返回x的双曲正弦(hyperbolic sine)
Math.cosh(x) 返回x的双曲余弦(hyperbolic cosine)
Math.tan(x) 方法返回一个数值的正切值
Math.tanh(x) 返回x的双曲正切(hyperbolic tangent)
Math.asinh(x) 返回x的反双曲正弦(inverse hyperbolic sine)
Math.acosh(x) 返回x的反双曲余弦(inverse hyperbolic cosine)
Math.atanh(x) 返回x的反双曲正切(inverse hyperbolic tangent)
指数运算符
ES2016新增了一个指数运算符(**)
2 ** 2; // 4 Math.pow(2, 2)
2 ** 3; // 8 Math.pow(2, 3)
// 指数运算符可以与等号结合,形成一个新的赋值运算符(**=)
let a = 1.5;
a **= 2; // a: 2.25
// v8引擎下Math.pow的值和指数运算有一定的差别
Math.pow(99, 99) === 99 ** 99; // false
// 但是如果你在firfox浏览器下(60)
Math.pow(99, 99) === 99 ** 99; // true