整数和浮点数
-
规则
- 在JavaScript语言的底层,根本没有整数,所有数字都是小数(64位浮点数)
- JavaScript内部,所有数字都是以64位浮点数形式储存,即使整数也是如此,故1和1.0是完全相同的
1 === 1.0 //true
- 由于浮点数不是精确的值,所以涉及小数的比较和运算要特别小心
0.3 / 0.1 //2.9999999999999996
0.1 + 0.2 == 0.3 //false
0.1 + 0.2 === 0.3 //false
(0.3 - 0.2) == (0.2 - 0.1) //false
(0.3 - 0.2) === (0.2 - 0.1) //false
-
运算
当某些运算只有整数才能完成时,JavaScript会自动把64位浮点数,转成32位整数,然后再进行运算
数值精度
根据国际标准IEEE 754,JavaScript浮点数的64个二进制位,从最左边开始,是这样组成的
第1位:符号位(决定数值正负),0表示正数,1表示负数
第2位到第12位:储存指数部分(决定数值大小)
第13位到第64位:储存小数部分(决定数值精度,即有效数字)
IEEE 754规定,有效数字第一位默认总是1,不保存在64位浮点数之中。也就是说,有效数字总是1.xx...xx的形式,其中xx..xx的部分保存在64位浮点数之中,最长可能为52位。因此,JavaScript提供的有效数字最长为53个二进制位
精度最多只能到53个二进制位,这意味着,绝对值小于2的53次方的整数,即-(253-1)到253-1,都可以精确表示
当数值大于2的53次方后,整数运算的结果开始出现错误,故大于等于2的53次方的数值,都无法保持精度
Math.pow(2, 53) //9007199254740992
Math.pow(2, 53) + 1 //9007199254740992
Math.pow(2, 53) + 2 //9007199254740994
Math.pow(2, 53) + 3 //9007199254740996
Math.pow(2, 53) + 4 //9007199254740996
//从上面示例可以看到,大于2的53次方以后,整数运算的结果开始出现错误
数值范围
根据标准,64位浮点数的指数部分的长度是11个二进制位,意味着指数部分的最大值是2047(211-1)。也就是说,64位浮点数的指数部分的值最大为2047,分出一半表示负数,则JavaScript能够表示的数值范围为21024到2-1023(开区间),超出这个范围的数无法表示
如果指数部分等于或超过最大正值1024,JavaScript会返回Infinity,这称为“正向溢出”
JavaScript所能表示的最大正数和最大负数为
Number.MAX_VALUE //1.7976931348623157e+308
-Number.MAX_VALUE //-1.7976931348623157e+308
如果指数部分等于或超过最小负值-1023(即非常接近0),JavaScript会直接把这个数转为0,这称为“负向溢出”
JavaScript所能表示的最小正数和最小负数为
Number.MIN_VALUE //5e-324
-Number.MIN_VALUE //-5e-324
表示方法
-
十进制
35
-
十六进制
0xFF
-
科学计数法
科学计数法允许字母 e 或 E 的后面,跟着一个整数,表示这个数值的指数部分
123e3 //123000
123e-3 //0.123
-3.1E+12
.1e-23
以下两种情况JavaScript会自动将数值转为科学计数法表示,其他情况都采用字面形式直接表示
- 小数点前的数字多于21位
//小数点前的数字多于21位,就自动转为科学计数法
1234567890123456789012 //1.2345678901234568e+21
//否则,就保持原来的字面形式
123456789012345678901 //123456789012345680000
- 小数点后的零多于5个
// 小数点后紧跟5个以上的零,就自动转为科学计数法
0.0000003 //3e-7
//否则,就保持原来的字面形式
0.000003 //0.000003
特殊值
-
正零和负零
JavaScript的64位浮点数之中,有一个二进制位是符号位,这意味着,任何一个数都有一个对应的负值,就连0也不例外
在JavaScript内部,实际上存在2个0:一个是+0,一个是-0,它们是等价的
+0 === -0 //true
0 === -0 //true
0 === +0 //true
几乎所有场合,正零和负零都会被当作正常的0
+0; 0
-0; 0
(-0).toString() //'0'
(+0).toString() //'0'
唯一有区别的场合是,+0或-0当作分母,返回的值是不相等的
1 / +0 === 1 / -0 //false
是因为除以+0得到的结果是+Infinity,除以-0得到的结果是-Infinity
-
无穷(Infinity)
-
出现情况
-
1.正值太大或者负值太小,无法表示
Math.pow(2, Math.pow(2, 100)) //Infinity
2.非0数除以0
由于数值正向溢出(overflow)、负向溢出(underflow)和被0除,JavaScript都不报错,而是返回Infinity,所以单纯的数学运算几乎没有可能抛出错误
1 / +0 //+Infinity
1 / -0 //-Infinity
-1 / +0 //-Infinity
-1 / -0 //Infinity
-
大小比较
Infinity大于一切数值(除了NaN),-Infinity小于一切数值(除了NaN)
Infinity > 10000000 //true
-Infinity < 10000000 //true
和NaN比较结果永远为false
Infinity > NaN //false
Infinity < NaN //false
-Infinity < NaN //false
-Infinity < NaN //false
-
运算规则
1.Infinity和0
0 * Infinity //NaN
0 / Infinity //0
Infinity / 0 //Infinity
2.Infinity和null:存在隐式类型数据转换,会将null转化为0,等同于和0做计算
null * Infinity //NaN
null / Infinity //0
Infinity / null //Infinity
3.Infinity和undefined:存在隐式类型数据转换,会将undefined转化为NaN,所有结果均为NaN
undefined + Infinity //NaN
undefined - Infinity //NaN
undefined * Infinity //NaN
undefined / Infinity //NaN
Infinity / undefined //NaN
4.Infinity与Infinity
Infinity与Infinity加或者乘得到的还是Infinity
Infinity + Infinity //Infinity
Infinity * Infinity //Infinity
-Infinity * Infinity //-Infinity
-Infinity * -Infinity //Infinity
Infinity与Infinity减或者除得到的是NaN
Infinity - Infinity //NaN
Infinity / Infinity //NaN
-
判断 isFinite()
isFinite()函数返回一个布尔值,检查某个值是不是正常数值,当参数内为Infinity或者NaN时,返回false
注意:原理与isNaN()相同,会先对括号内的参数用Number()转换一,故使用时一定要注意参数内的数据类型
```javascript
isFinite(Infinity) //false
isFinite(NaN) //false
isFinite(true) //true
isFinite(-1) //true
##与数值相关的全局方法
####parseInt()
* #####用法
将字符串转换为整数
> parseInt('字符串',进制);
第二个参数为2~36之间的数字,如果不设置,则默认为10,即默认为十进制
* #####规则
* 如果参数不为字符串,则会将参数转换为字符串在进行转换
```javascript
parseInt(1.23) //1 等同于parseInt(String(1.23))
parseInt(1.23a) //报错
- 如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),则返回NaN
parseInt('.3') //NaN
parseInt('abc') //NaN
parseInt('') //NaN
parseInt(' ') //NaN
parseInt('+') //NaN
parseInt('+1') //1
- 如果字符串头部有空格,空格会被自动去除
parseInt(' 1') //1
- 字符串转为整数的时候,是一个个字符依次转换,如果遇到不能转为数字的字符,就不再进行下去,返回已经转好的部分
parseInt('8a') //8
parseInt('12**') //12
parseInt('12.34') //12
parseInt('15e2') //15
parseInt('15px') //15
- 如果字符串开头为0,则会将其按照十进制解析
parseInt('0100') //100
parseInt('00100') //100
- 如果字符串开头为0x或者0X,则会将其按照十六进制解析
parseInt('0x10') //16
parseInt('0X100') //256
- 对于会自动转为科学计数法的数字,parseInt会将科学计数法的表示方法视为字符串,因此导致一些奇怪的结果
parseInt('1000000000000000000000.5') //1 等同于parseInt('1e+21')
parseInt(0.0000008) //8 等同于parseInt('8e-7')
-
进制转换
- 不设置第二个参数
parseInt('100') //1 等同于parseInt('100',10)
- 设置第二个参数在2~36之间
parseInt('1000',2) //8
parseInt('1000',6) //216
parseInt('1000',8) //512
- 设置第二个参数为0、undefined和null,则直接忽略
parseInt('1000',0) //1000
parseInt('1000',undefined) //1000
parseInt('1000',null) //1000
- 如果第二个参数不是数值,会被自动转为一个整数,这个整数只有在2到36之间,才能得到有意义的结果,超出这个范围,则返回NaN
parseInt('10', 37) //NaN
parseInt('10', 1) //NaN
- 如果字符串包含对于指定进制无意义的字符,则从最高位开始,只返回可以转换的数值。如果最高位无法转换,则直接返回NaN
parseInt('1511', 2) //1 1是有意义的字符,5为无意义字符,停止转换,返回1
parseInt('511', 2) //NaN
- parseInt的第一个参数不是字符串,会被先转为字符串,这会导致一些令人意外的结果,对于八进制的前缀0尤其需要注意
parseInt(0x11, 36) //43
//由于第一个参数不为字符串,则进行一次数据转换String(0x11),结果为'17'
//然后再进行parseInt('17',36),对17进行三十六进制转换,结果即为43
parseInt(011,2) //NaN
//由于第一个参数不为字符串,则进行一次数据转换String(011),结果为'9'
//然后再进行parseInt('9',2),对9进行二进制转换
//由于9不是二进制的有效数字,故结果为NaN
parseFloat()
- 用法
将字符串转换为浮点数
parseFloat('字符串')
- 规则
- 如果参数不为字符串,则会将参数转换为字符串在进行转换
parseFloat(1.23) //1 等同于parseInt(String(1.23))
parseFloat(1.23a) //报错
- 如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号、小数点除外),则返回NaN
parseInt('.3') //0.3
parseInt('abc') //NaN
parseInt('') //NaN
parseInt(' ') //NaN
parseInt('+') //NaN
parseInt('+1.2') //1.2
- 如果字符串头部有空格,空格会被自动去除
parseInt(' .1') //0.1
- 字符串转为浮点数的时候,是一个个字符依次转换,如果遇到不能转为数字的字符,就不再进行下去,返回已经转好的部分
parseInt('8.5a') //8
parseInt('12.**34') //12
parseInt('12.34') //12.34
parseInt('15.2e2') //15.2
parseInt('15.2px') //15.2
- 如果字符串符合科学计数法,则会进行相应的转换
parseFloat('314e-2') //3.14
parseFloat('0.0314E+2') //3.14
参考链接:http://javascript.ruanyifeng.com/grammar/number.html