您的位置:首页 > Web前端 > JavaScript

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

2016-11-14 20:07 471 查看


1、概述

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

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

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

1 + 1.0
// 2


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

12345678901234567
// 12345678901234568(只精确16位数字,多余的数字可能不准确)

12345678901234560
// 12345678901234560(只精确16位数字,多余的数字可能不准确)

0.1234567890123456
// 0.1234567890123456(精确16位数字)

1.123456789012345
// 1.123456789012345(精确16位数字)

123.1234567890123
// 123.1234567890123(精确16位数字)

123.12345678901233
// 123.12345678901232(只精确16位数字,多余的数字可能不准确)


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

0.3 / 0.1
// 2.9999999999999996


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

因此,JavaScript提供的有效数字的精度为53个二进制位(IEEE 754规定有效数字第一位默认为1,再加上后面的52位),也就是说,小于2的53次方的整数都可以精确表示。
Math.pow(2, 53)  // 54个二进制位
// 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次方以后,整数运算的结果开始出现错误。所以,大于等于2的53次方的数值,都无法保持精度。
Math.pow(2, 53)
// 9007199254740992

9007199254740992111
// 9007199254740992000


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

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


2、表示及表示转换

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

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

如:
1234567890123456789012
// 1.2345678901234568e+21
// (整数部分超过16位数字,多余的数字将不精确
// 整体超过21位数字,使用科学计数法表示)

123456789012345678901
// 123456789012345678901
// (整数部分超过16位数字,多余的数字将不精确
// 但整体尚未超过21位数字,使用字面形式直接表示)

0.0000001
// 1e-7
// (小数部分开头超过5个连续0,使用科学计数法表示)

0.0001002
// 0.0001002
// (小数部分开头没有超过5个连续0,使用字面形式直接表示)


数值表示转换:
// 转换为科学计数表示
(123).toExponential(1);
// "1.2e+2"

(123).toExponential(5);
// "1.23000e+2"


3、进制及进制转换

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

011
// 八进制
// 相当于十进制的9(1*8+1)

0x11
// 十六进制
// 相当于十进制的17(1*16+1)


进制转换:
// 1、十进制转换其他进制

// 十进制转换为二进制
(123).toString(2);
// "1111011"

// 十进制转换为八进制
(123).toString(8);
// "173"

// 十进制转换为十六进制
(123).toString(16);
// "7b"

// 2、八进制转换其他进制

// 八进制转换为二进制
(0123).toString(2);
// "1010011"

// 八进制转换为十进制
(0123).toString(10);
// "83"

// 八进制转换为十六进制
(0123).toString(16);
// "53"

// 3、十六进制转换其他进制

// 十六进制转换为二进制
(0x123).toString(2);
// "100100011"

// 八进制转换为八进制
(0x123).toString(8);
// "443"

// 八进制转换为十进制
(0x123).toString(10);
// "291"


4、parseInt与parseFloat

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

parseInt
语法为:
parseInt(string, radix);
// string为待解析的字符串或数值
// radix表示待解析的字符串或数值的进制


parseInt
有个误区,通常认为该方法是将字符串或数值转换为指定进制。比如:
// => 错误认为会将十进制的10转换为八进制的12
parseInt(10, 8);


parseInt没有转换进制的功能,它的字面意思是解析(parse)而不是转换(change),它只是将目标解析为十进制,所以:
// 返回的结果不是8,而是NaN
// 因为八进制当中没有8这个数值
parseInt(8, 8);


parseInt的解析有以下特点:

A、会省略待解析的字符串的开头和结尾空格:
parseInt('  1  ');
// 1

parseInt('1');
// 1


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

parseInt('2013');
// 2013

parseInt('-99°C');
// -99

parseInt('-99');
// -99

parseInt('+99°C');
// 99

parseInt('+99');
// 99

parseInt('010-1234567');
// 10

parseInt('10-1234567');
// 10

parseInt('-010-1234567');
// 10

parseInt('-10-1234567');
// 10

parseInt('0a11');
// 0

parseInt('0x11');
// 17(并不是0)


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

parseInt(011);
// 9=1*8+1

parseInt("011");
// 11

parseInt(11,8);
// 9=1*8+1

parseInt(0x11);
// 17=1*16+1

parseInt("0x11");
// 17=parseInt(0x11)

parseInt(11,16);
// 17=1*16+1


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

D、不符合以上规则的将解析为NaN:
parseInt('云淡然');
// NaN(开头没有数字)

parseInt('云淡然2013');
// NaN(数字不在开头)

parseInt('--1');
// NaN(正负号后面不是数字)

parseInt(8, 8);
// NaN(数字8不在八进制中)


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

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

如:
parseFloat(1234567890123456);
// 1234567890123456

parseFloat(12345678901234567);
// 12345678901234568(不同,参考概述)

parseFloat(123.1234567890123);
// 123.1234567890123

parseFloat(123.12345678901233);
// 123.12345678901232(不同,参考概述)

parseFloat(123456789012345678901);
// 123456789012345678901

parseFloat(1234567890123456789012);
// 1.2345678901234568e+21(科学计数法,参考表示)

parseFloat(0.0001002);
// 0.0001002

parseFloat(0.0000002);
// 2e-7(科学计数法,参考表示)


5、Number

Number是将数字或字符串类型转换为数值对象,必要时两者之间可以自动转换。
var a=1;
var b=Number(a);

a.toFixed(2);
// 1.00

b.toFixed(2);
// 1.00

a(数字基本类型)和b(数字对象类型)都有了对象属性,a自动转换为数字对象类型


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


6、参考资料

http://javascript.ruanyifeng.com/grammar/number.html
http://www.w3school.com.cn/js/js_obj_number.asp
http://www.w3school.com.cn/js/jsref_parseInt.asp
http://www.w3school.com.cn/js/jsref_parseFloat.asp
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: