JavaScript数据类型之Number类型

Number数据类型

JavaScript所有数字都是64位浮点数,即使整数也是

1 === 1.0 // true

八进制字面量,以0开头。(严格模式下,八进制字面量无效,会报语法错误)

console.log(012) // 10
console.log(018) // 18 如果后面的数字超过0~7范围,则会忽略前面的0,后面的数值作为十进制

十六进制的字面量,以0x开头

console.log(0x10) // 16

Number.MAX_VALUE 可表示的最大的数。超过则为+Infinity 正无穷
Number.MIN_VALUE 可表示的最小的数。小于则为-Infinity 负无穷

Number.MAX_SAFE_INTEGER, 最大的安全整数 =  2^53  -  1 = 9007199254740991

Number.MIN_SAFE_INTEGER, 最小的安全整数 =  - 2^53 + 1 = - 9007199254740991

注:超过这个范围的整数的算数运算不精确,如

9007199254740992 === 9007199254740992 +1  // true
9007199254740991 + 2 // 9007199254740992
-9007199254740992 - 3 // -9007199254740996

NaN(not a number)

NaN 用于表示一个本来要返回数值的操作数未返回数值的情况。

parseInt('a') // NaN
0/0 // NaN

NaN不与任何值相等,包括本身(可以用来判断NaN类型)

0/0 === 0/0 // false

可以用isNaN()判断是否为NaN

isNaN(NaN) // true
isNaN('a') // true 全局的isNaN会先将传入的参数转为数值在进行判断。'a'转为数值为NaN,所以为true
Number.isNaN('a') // false Number的静态方法不会将传入的参数转为数值。所以是false
isNaN(1) // false

NaN与任何数值操作都为NaN

为什么最大的安全整数是 - 2^53 ~ 2^53 (不包含边界-2^53和2^53)  

JavaScript 里的数字是采用 IEEE 754 标准的 64 位双精度浮点数。1个符号位,11个指数位,尾数位52个(即52个有效数字),超出的部分舍0进1。

IEEE 754规定,有效数字第一位默认总是1,不保存在64位浮点数之中,所以除了52个尾数位还有1个有效数字,即可以保存53位有效数字。

计算机存储时会把尾数超过52位的部分截取掉
2^53转为二进制为 1.000...(52个0)
2^53转为二进制为 1.000...1(52个0),最终存储到计算机也是1.000...(52个0)
所以Math.pow(2, 53) + 1 === Math.pow(2, 53) 为true

浮点数计算不精确问题

0.1 + 0.2 // 0.30000000000000004
1.335.toFixed(2) // 1.33 toFixed不会四舍五入
(0.07 * 100 + 0.14 * 100 )/100 // 即使通过乘法转为整数去计算,误差也还是存在

主要原因:因为计算机存储时会把尾数超过52位的部分截取掉,0.1和0.2转为二进制会出现无限循环,最终超过的位数会被截取掉,所以导致计算不精确

0.1 >> 0.0001 1001 1001 …(无限循环)

解决:使用第三方库如bignumberMath.js

科学计数法表示的两种情况

1、小数点前的位数多于21位

123456789123456789123456 // 1.234567891234568e+23 即1.234567891234568*10^23

2、小数点后连续6个0或以上

0.0000001  // 1e-7 即1 * 10^-7

处理科学计数法的显示问题:

function toNonExponential(num) {
    // 先转为科学计数法
    var m = num.toExponential().match(/\d(?:\.(\d*))?e([+-]\d+)/);
    return num.toFixed(Math.max(0, (m[1] || '').length - m[2]));
}

相关api

parseInt(string, radix):将字符串转为数值

只传入第一个参数:

1、parseInt会从第一个非空格字符开始转换 ,直到解析到一个无效的数值字符,如果不是数值字符(如果是正负号后面紧跟着数值除外),则返回NaN

parseInt('   1') // 1  parseInt会从第一个非空格字符开始转换 
parseInt('+') // NaN
parseInt('+1.345') // 如果正负号紧跟着数值,则不会返回NaN
parseInt('   123k') // 123 截取遇到第一个非字符为止
parseInt('1.23') // 1
parseInt('') // NaN 如果不是数值字符,则返回NAN

2、如果传入的不是字符串,则会先转为字符串

parseInt(1) === parseInt('1') // 1

3、如果字符串以"0x"开头,就会被解析为十六进制整数

parseInt('0x10') // 16
parseInt('10', 16) // 16 如果传入第二个参数,0x可以省略

4、在严格模式下,字符串以"0"开头,就会被解析为十进制整

parseInt('010') // 10

5、如果第一个参数传入的数值能被转换为科学计数法,则会先转为数值的科学计数法,在转为字符串

parseInt(1000000000000000000001) // 1
1000000000000000000001 会先转为 1e+21
即 parseInt(1e+21) === 1

6、传入的第二个参数会被转为整数,如果传的不是有效数值,则无效

parseInt(10, '2') === parseInt(10, 2) // 2
parseInt(10, 0) // 10
parseInt(10, null) // 10
parseInt(10, undefined) // 10
parseInt(10, 'abc') // 10

7、如果传入的第二个参数为1、或者大于36,则返回NaN

parseInt(10, 1) // NaN
parseInt(10, 37) // NaN

8、如果传入的值,无法转为第二参数所需要的进制,则返回NaN

parseInt(3, 2) // NaN 3无法用2进制解析

9、parseInt会尝试尽量把传入的值,以传入的radix的进制去解析为数值,直到遇到不能解析的字符为止

parseInt(Infinity, 19) // 18 Infinity会先转为字符串,然后I在19进制中为18,所以最终返回18

面试题:

1、[1,2,3].map(parseInt)

[1,2,3].map(parseInt) // [1, NaN, NaN]
等同于 
[1,2,3].map((val, index) => { 
    return parseInt(val, index)
})
即 parseInt(1, 0) // 1
parseInt(2, 1) // NaN
parseInt(3, 2) // NaN

2、"123".replace(/\d/g, parseInt)

"123".replace(/\d/g, (...arg) => console.log(arg)) 
打印出:
["1", 0, "123"]
["2", 1, "123"]
["3", 2, "123"]
所以 "123".replace(/\d/g, parseInt) // "1NaNNaN"

注:如果是简单字符串要转为 数值,则可以使用~~代替

~~'1.1' // 1
~~'12345678910' // -542333997 如果超过10位则不精确

parseFloat(string):将字符串转为浮点数

1、parseFloat会从第一个非空格字符开始转换 ,直到解析到一个无效的浮点数

parseFloat('00001.0') // 1.0
parseFloat('1.1.1') // 1.1 //解析到第二个小数点为无效浮点数,停止解析

2、如果字符串符合科学计数法,则会进行相应的转换

parseFloat('12e-2') // 1.2
parseFloat('0.0123e+1') // 0.123

3、如果第一个字符不能转化为浮点数,则返回NaN

parseFloat([]) // NaN
// [], undefined, null, '' 都返回NaN

4、parseFloat只解析十进制数

parseFloat('0x') // 0

num.toFixed(num):把num 四舍五入为指定小数位数的数字的字符串,num介于0-20之间,不传默认为0

1、返回结果是字符串

1.55555.toFixed(2) // '1.56' 返回的是字符串
+1.55555.toFixed(2) // -1.56 返回字符串后,因为前面的+号,会转为number类型

2、浮点数不一定会精确的四舍五入

2.55 // toFixed(1) // 2.5 浮点数不一定会精确的四舍五入
1.335.toFixed(2) // 1.33

isFinite(num) :判断传入的值是否是一个有穷数。

isFinite(Infinity) // false Infinity、-Infinity、NaN和undefined这几个值都会返回false
isFinite(1) // true
isFinite('1') // true 
Number.isFinite('1') // false 
和全局的 isFinite() 函数相比,Number.isFinite不会强制将一个非数值的参数转换成数值,只有数值类型的值,且是有穷的(finite),才返回 true

Number.isInteger(value):判断此参数是否为整数

Number.isInteger("1") // false 数值字符串返回false
Number.isInteger(1.1) // false
Number.isInteger(1) // true
Number.isInteger(1.0) // true 1.0等同于1

Number.isSafeInteger(value):判断传入的参数值是否是一个“安全整数”

安全整数的范围是 - 2^53 ~ 2^53,不包含边界

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值