JS学习33:数值类型基础知识

1、概述

JavaScript 不是类型语言。与许多其他编程语言不同,JavaScript 不定义不同类型的数字,比如整数、短、长、浮点等等。

JavaScript 中的所有数字都存储为根为 10 的 64 位(8 比特),浮点数。

所以在 JavaScript 内部,所有数字都是以64位浮点数形式储存,即使整数也是如此。例如:


  
  
  1. 1 === 1.0
  2. // true
  3. 1 + 1.0
  4. // 2

所以在 javascript 中,精确的整数(不使用小数点或指数计数法)最多为 16 位数字;精确的浮点数(包含整数和小数部分,不包含小数点)的最大位数也是 16位数字,例如:


  
  
  1. 1234567890123456
  2. // 1234567890123456(精确16位数字)
  3. 12345678901234567
  4. // 12345678901234568(只精确16位数字,多余的数字可能不准确)
  5. 12345678901234560
  6. // 12345678901234560(只精确16位数字,多余的数字可能不准确)
  7. 0.1234567890123456
  8. // 0.1234567890123456(精确16位数字)
  9. 1.123456789012345
  10. // 1.123456789012345(精确16位数字)
  11. 123.1234567890123
  12. // 123.1234567890123(精确16位数字)
  13. 123.12345678901233
  14. // 123.12345678901232(只精确16位数字,多余的数字可能不准确)

但是浮点运算并不总是 100% 准确,由于浮点数不是精确的值,所以涉及小数的比较和运算要特别小心,例:


  
  
  1. 0.1 + 0.2 === 0.3
  2. // 0.1+0.2 = 0.30000000000000004
  3. // false
  4. 0.3 / 0.1
  5. // 2.9999999999999996

根据国际标准IEEE 754,64位浮点数格式的64个二进制位中,第0位到第51位储存有效数字部分,第52到第62位储存指数部分,第63位是符号位,0表示正数,1表示负数。

因此,JavaScript提供的有效数字的精度为53个二进制位(IEEE 754规定有效数字第一位默认为1,再加上后面的52位),也就是说,小于2的53次方的整数都可以精确表示。


  
  
  1. Math.pow(2, 53) // 54个二进制位
  2. // 9007199254740992
  3. Math.pow(2, 53) + 1
  4. // 9007199254740992
  5. Math.pow(2, 53) + 2
  6. // 9007199254740994
  7. Math.pow(2, 53) + 3
  8. // 9007199254740996
  9. Math.pow(2, 53) + 4
  10. // 9007199254740996

从上面示例可以看到,大于2的53次方以后,整数运算的结果开始出现错误。所以,大于等于2的53次方的数值,都无法保持精度。


  
  
  1. Math.pow(2, 53)
  2. // 9007199254740992
  3. 9007199254740992111
  4. // 9007199254740992000

上面示例表明,大于2的53次方以后,多出来的有效数字(最后三位的111变成了000)都会无法保存,变成0。

另一方面,64位浮点数的指数部分的长度是11个二进制位,意味着指数部分的最大值是2047(2的11次方减1)。所以,JavaScript能够表示的数值范围为(-22048, 22048),超出这个范围的数无法表示。

2、表示及表示转换

数值可以字面形式直接表示,也可以采用科学计数法表示。以下两种情况,JavaScript会自动将数值转为科学计数法表示,其他情况都采用字面形式直接表示。

  1. 小数点前的数字多于21位。
  2. 小数点后的零多于5个。

如:


  
  
  1. 1234567890123456789012
  2. // 1.2345678901234568e+21
  3. // (整数部分超过16位数字,多余的数字将不精确
  4. // 整体超过21位数字,使用科学计数法表示)
  5. 123456789012345678901
  6. // 123456789012345678901
  7. // (整数部分超过16位数字,多余的数字将不精确
  8. // 但整体尚未超过21位数字,使用字面形式直接表示)
  9. 0.0000001
  10. // 1e-7
  11. // (小数部分开头超过5个连续0,使用科学计数法表示)
  12. 0.0001002
  13. // 0.0001002
  14. // (小数部分开头没有超过5个连续0,使用字面形式直接表示)

数值表示转换:


  
  
  1. // 转换为科学计数表示
  2. (123).toExponential(1);
  3. // "1.2e+2"
  4. (123).toExponential(5);
  5. // "1.23000e+2"

3、进制及进制转换

任何数值其实都可以转换为任何进制,其中常用的进制有十进制、二进制、八进制、十六进制,其中二进制、八进制、十六进制是应计算机而生的,因为他们都是2的N次幂。在表示不同进制时:


  
  
  1. 11
  2. // 十进制
  3. // 相当于十进制的11(1*10+1)
  4. 011
  5. // 八进制
  6. // 相当于十进制的9(1*8+1)
  7. 0x11
  8. // 十六进制
  9. // 相当于十进制的17(1*16+1)

进制转换:


  
  
  1. // 1、十进制转换其他进制
  2. // 十进制转换为二进制
  3. (123).toString(2);
  4. // "1111011"
  5. // 十进制转换为八进制
  6. (123).toString(8);
  7. // "173"
  8. // 十进制转换为十六进制
  9. (123).toString(16);
  10. // "7b"
  11. // 2、八进制转换其他进制
  12. // 八进制转换为二进制
  13. (0123).toString(2);
  14. // "1010011"
  15. // 八进制转换为十进制
  16. (0123).toString(10);
  17. // "83"
  18. // 八进制转换为十六进制
  19. (0123).toString(16);
  20. // "53"
  21. // 3、十六进制转换其他进制
  22. // 十六进制转换为二进制
  23. (0x123).toString(2);
  24. // "100100011"
  25. // 八进制转换为八进制
  26. (0x123).toString(8);
  27. // "443"
  28. // 八进制转换为十进制
  29. (0x123).toString(10);
  30. // "291"

4、parseInt与parseFloat

  • parseInt 是将数值或字符串解析为十进制数值的整数。
  • parseFloat 是将数值或字符串解析为十进制浮点数。

parseInt语法为:


  
  
  1. parseInt(string, radix);
  2. // string为待解析的字符串或数值
  3. // radix表示待解析的字符串或数值的进制

parseInt 有个误区,通常认为该方法是将字符串或数值转换为指定进制。比如:


  
  
  1. // => 错误认为会将十进制的10转换为八进制的12
  2. parseInt(10, 8);

parseInt没有转换进制的功能,它的字面意思是解析(parse)而不是转换(change),它只是将目标解析为十进制,所以:


  
  
  1. // 返回的结果不是8,而是NaN
  2. // 因为八进制当中没有8这个数值
  3. parseInt(8, 8);

parseInt的解析有以下特点:

A、会省略待解析的字符串的开头和结尾空格:


  
  
  1. parseInt(' 1 ');
  2. // 1
  3. parseInt('1');
  4. // 1

B、只保留从开头(不包含正负号)开始的连续数字,并会省略连续数字开头的0(但0后面为x较为特殊,表示十六进制):


  
  
  1. parseInt('2013年11月14日');
  2. // 2013
  3. parseInt('2013');
  4. // 2013
  5. parseInt('-99°C');
  6. // -99
  7. parseInt('-99');
  8. // -99
  9. parseInt('+99°C');
  10. // 99
  11. parseInt('+99');
  12. // 99
  13. parseInt('010-1234567');
  14. // 10
  15. parseInt('10-1234567');
  16. // 10
  17. parseInt('-010-1234567');
  18. // 10
  19. parseInt('-10-1234567');
  20. // 10
  21. parseInt('0a11');
  22. // 0
  23. parseInt('0x11');
  24. // 17(并不是0)

C、进制解析,可以解析[2,32]之间进制的数值为十进制:


  
  
  1. parseInt(011);
  2. // 9=1*8+1
  3. parseInt("011");
  4. // 11
  5. parseInt(11,8);
  6. // 9=1*8+1
  7. parseInt(0x11);
  8. // 17=1*16+1
  9. parseInt("0x11");
  10. // 17=parseInt(0x11)
  11. parseInt(11,16);
  12. // 17=1*16+1

parseInt的八进制和十六进制的字符串解析比较特殊,容易引起误会。

D、不符合以上规则的将解析为NaN:


  
  
  1. parseInt('云淡然');
  2. // NaN(开头没有数字)
  3. parseInt('云淡然2013');
  4. // NaN(数字不在开头)
  5. parseInt('--1');
  6. // NaN(正负号后面不是数字)
  7. parseInt(8, 8);
  8. // NaN(数字8不在八进制中)

parseFloat与parseInt的解析规则几乎一致,区别在于:

  • A、parseFloat支持小数
  • B、parseFloat符合概述和表示的规则

如:


  
  
  1. parseFloat(1234567890123456);
  2. // 1234567890123456
  3. parseFloat(12345678901234567);
  4. // 12345678901234568(不同,参考概述)
  5. parseFloat(123.1234567890123);
  6. // 123.1234567890123
  7. parseFloat(123.12345678901233);
  8. // 123.12345678901232(不同,参考概述)
  9. parseFloat(123456789012345678901);
  10. // 123456789012345678901
  11. parseFloat(1234567890123456789012);
  12. // 1.2345678901234568e+21(科学计数法,参考表示)
  13. parseFloat(0.0001002);
  14. // 0.0001002
  15. parseFloat(0.0000002);
  16. // 2e-7(科学计数法,参考表示)

5、Number

Number是将数字或字符串类型转换为数值对象,必要时两者之间可以自动转换。


  
  
  1. var a=1;
  2. var b=Number(a);
  3. a.toFixed(2);
  4. // 1.00
  5. b.toFixed(2);
  6. // 1.00
  7. a(数字基本类型)和b(数字对象类型)都有了对象属性,a自动转换为数字对象类型

和parseInt以及parseFloat类似,Number方法会先将参数解析,然后转换为数值对象。

6、参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值