JavaScript简明教程-数值

517 阅读11分钟

基本概念

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_INTEGERNumber.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