JavaScript 数据类型之数字 Number
1.定义
JavaScript 只有一种数字类型。JavaScript 中的所有数字都存储为根为 10 的 64 位(8 比特),浮点数。
JavaScript 数字可以使用也可以不使用小数点来书写。
2.创建方法
var n = 123; // 123
var n2 = 12.3; // 12.3
var n3 = new Number(1); // Number {1}
var n4 = Number(1); // 1
...
2.1 极大或极小的数字可通过科学(指数)计数法来写
var n = 123e8; // 12300000000
var n2 = 123e-5; // 0.00123
3. JavaScript 数字特性
3.1 JavaScript 内部,所有数字都是以64位浮点数形式储存,即使整数也是如此。所以,1与1.0是相同的,是同一个数。
1 === 1.0; // true
2.0 === 2; // true
3.2 由于浮点数不是精确的值,所以涉及小数的比较和运算要特别小心
0.3 - 0.1; // 0.19999999999999998
0.3 / 0.1; // 2.9999999999999996
(0.2 - 0.1) === (0.3 - 0.2); // false
3.3 数值精度
- 根据国际标准 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次方的整数,即-(2e53 - 1)到2e53 - 1,都可以精确表示。
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次方以后,多出来的有效数字(最后三位的111)都会无法保存,变成0。
9007199254740992111 === 9007199254740992000; // true
3.4 数值范围
- 根据标准,64位浮点数的指数部分的长度是11个二进制位,意味着指数部分的最大值是2047(2的11次方减1)。也就是说,64位浮点数的指数部分的值最大为2047,分出一半表示负数,则 JavaScript 能够表示的数值范围为2e1024到2e-1023(开区间),超出这个范围的数无法表示。
- 如果指数部分等于或超过最大正值1024,JavaScript 会返回Infinity(关于Infinity的介绍参见下文),这称为“正向溢出”;如果等于或超过最小负值-1023(即非常接近0),JavaScript 会直接把这个数转为0,这称为“负向溢出”
- 最大值及最小值 JavaScript 提供Number对象的MAX_VALUE和MIN_VALUE属性表示
Number.MAX_VALUE; // 1.7976931348623157e+308
Number.MIN_VALUE; // 5e-324
3.5 数值的表示法
12.3e+10; // 123000000000
123e-2; // 1.23
.3e+10; // 3000000000
-3E+4; // -30000
- 以下两种情况,JavaScript 会自动将数值转为科学计数法表示,其他情况都采用字面形式直接表示。
- 小数点前的数字多于21位。
1234567890987654321123; // 1.2345678909876543e+21
- 小数点后的零多于5个。
0.000000212; // 2.12e-7 0.00000212; // 0.00000212
- 小数点前的数字多于21位。
4. 数值的进制
- 使用字面量( literal) 时, JavaScript 对整数提供四种进制的表示方法: 十进制、 十六进制、 八进制、 二进制。
- 十进制: 没有前导0的数值。
123; // 123
- 有前导0的数值会被视为八进制,但是如果前导0后面有数字8和9,则该数值被视为十进制
0888; // 888 0777; // 511
- 八进制: 有前缀0o或0O的数值, 或者有前导0、 且只用到0 - 7 的八个阿拉伯数字的数值。
0o167; // 119 0O111; // 73 0o9; // SyntaxError
- 十六进制: 有前缀0x或0X的数值。
0xabcdef; // 11259375 0X11; // 17
- 二进制: 有前缀0b或0B的数值。
0b100; // 4 0B110; // 6
- 十进制: 没有前导0的数值。
- 进制转换
- 十进制转其他 toString()
(7).toString(2); // "111" (86).toString(8); // "126" (123).toString(16); // "7b" (123).toString(20); // "63" ...
- 其他转十进制 parseInt(), 第二个参数只能是[2,36]或者0,否则都是NaN。如果第二个参数是0、undefined和null,则直接忽略。
parseInt(100, 1); // NaN parseInt(100, 2); // 4 parseInt(100, 8); // 64 parseInt(100, 16); // 256 parseInt(100, 37); // NaN parseInt('10', 0); // 10 parseInt('10', null); // 10 parseInt('10', undefined); // 10
- 十进制转其他 toString()
5. 正零和负零
0 === +0; // true
0 === -0; // true
-0 === +0; // true
5.1 唯一有区别的场合是,+0或-0当作分母,返回的值是不相等的。
1 / +0; // Infinity
1 / -0; // -Infinity
6. NaN 是 JavaScript 的特殊值,表示“非数字”(Not a Number),主要出现在将字符串解析成数字出错的场合。NaN 与任何数字进行运算都返回 NaN。
typeof NaN; // "number"
NaN === NaN; // false
isNaN(NaN); // true
isNaN(1); // false
isNaN(""); // false 判断前会先对""进行类型转换,相当与isNaN(0);
isNaN("hello"); // true 判断前会先对"hello"进行类型转换,相当与isNaN(NaN);
isNaN("123"); // false 判断前会先对"123"进行类型转换,相当与isNaN(123);
isNaN([]); // false 判断前会先对[]进行类型转换,相当与isNaN(0);
isNaN([1]); // false 判断前会先对[1]进行类型转换,相当与isNaN(1);
isNaN({}); // true 判断前会先对{}进行类型转换,相当与isNaN(NaN);
7. 使用Number函数,可以将任意类型的值转化成数值。Number方法的参数是对象时,将返回NaN,除非是包含单个数值的数组。
Number([]); // 0
Number([""]); // 0
Number([1]); // 1
Number(['1']); // 1
Number({}); // NaN
Number(''); // 0
7.1 原始类型的值主要是字符串、布尔值、undefined和null,它们都能被Number转成数值或NaN
Number(undefined); // NaN
Number(null); // 0
Number(true); // 1
Number(false); // 0
Number("adv"); // NaN
Number("444"); // 444
Number("4ad"); // NaN Number函数整体转换字符串的类型
parseInt("4ad"); // 4 parseInt逐个解析字符
7.2 Number函数会自动过滤一个字符串前导和后缀的空格
Number('\v\t\r123\v'); // 123
Number(" 456 "); // 456
Number(" 45 6 "); // NaN
8. number 转换规则
- 调用对象自身的valueOf方法。 如果返回原始类型的值, 则直接对该值使用Number函数,不再进行后续步骤。
Number({ valueOf(){ return 123; } }); // 123 Number({ valueOf() { return 2; }, toString() { return 3; } }); // 2
- 如果valueOf方法返回的还是对象,则改为调用对象自身的toString方法。如果toString方法返回原始类型的值, 则对该值使用Number函数,不再进行后续步骤。
Number({ valueOf(){ return {}; }, toString(){ return 22; } }); // 22
- 如果toString方法返回的是对象, 就报错。
Number({ valueOf(){ return {}; }, toString(){ return []; } }); // 报错 TypeError: Cannot convert object to primitive value
9. Infinity Infinity大于一切数值(除了NaN),-Infinity小于一切数值(除了NaN)。
0 / 0; // NaN
1 / 0; // Infinity
Infinity > 10000; // true
Infinity > NaN; // false
-Infinity < -10000; // true
-Infinity < NaN; // false
5 * Infinity; // Infinity
5 - Infinity; // -Infinity
Infinity / 5; // Infinity
5 / Infinity; // 0
0 * Infinity; // NaN
0 / Infinity; // 0
Infinity / 0; // Infinity
null * Infinity; // NaN
null / Infinity; // 0
Infinity / null; // Infinity
undefined + Infinity; // NaN
undefined - Infinity; // NaN
undefined * Infinity; // NaN
undefined / Infinity; // NaN
Infinity / undefined; // NaN
Infinity + Infinity; // Infinity
Infinity * Infinity; // Infinity
Infinity - Infinity; // NaN
Infinity / Infinity; // NaN
10. isFinite函数 判断是否为 boolean 类型
isFinite(Infinity); // false
isFinite(-1); // true
isFinite(true); // true
isFinite(false); // true
isFinite(NaN); // false
11. parseInt() parseInt方法用于将字符串转为整数
parseInt('123'); // 123
parseInt(' 12.'); // 12
parseInt(''); // NaN
parseInt(0777); // 511 这里是将二进制数 0777 转换成 十进制
11.1 对于那些会自动转为科学计数法的数字,parseInt会将科学计数法的表示方法视为字符串,因此导致一些奇怪的结果
parseInt(1000000000000000000000000000000000000.12); // 1
parseInt(1.12e12); // 1
parseInt(0.000000094); // 9
parseInt(9.4e-8); // 9
11.2 如果字符串包含对于指定进制无意义的字符, 则从最高位开始, 只返回可以转换的数值。 如果最高位无法转换, 则直接返回NaN。
parseInt('1546', 2); // 1
parseInt('546', 2); // NaN
parseInt(0x11, 36); // 43 十六进制的0x11会被先转为十进制的17,再转为字符串。然后,再用36进制解读字符串17,最后返回结果43。
parseInt(011, 2); // NaN 第一行的011会被先转为字符串9,因为9不是二进制的有效字符,所以返回NaN。
// 第二行的字符串011,会被当作二进制处理,返回3。
12. parseFloat方法用于将一个字符串转为浮点数。
parseFloat('314e-2'); // 3.14
parseFloat('0.0314E+2'); // 3.14
parseFloat('3.14more non-digit characters'); // 3.14
parseFloat('\t\v\r12.34\n '); // 12.34
parseFloat([]); // NaN
parseFloat('FF2'); // NaN
parseFloat(''); // NaN
parseFloat(true); // NaN
Number(true); // 1
parseFloat(null); // NaN
Number(null); // 0
parseFloat(''); // NaN
Number(''); // 0
parseFloat('123.45#') // 123.45
Number('123.45#') // NaN
13. Number 对象的属性
- Number.POSITIVE_INFINITY:正的无限,指向Infinity。
Number.POSITIVE_INFINITY; // Infinity
- Number.NEGATIVE_INFINITY:负的无限,指向-Infinity。
Number.NEGATIVE_INFINITY; // -Infinity
- Number.NaN:表示非数值,指向NaN。
Number.NaN; // NaN
- Number.MAX_VALUE:表示最大的正数,相应的,最小的负数为-Number.MAX_VALUE。
Number.MAX_VALUE; // 1.7976931348623157e+308
- Number.MIN_VALUE:表示最小的正数(即最接近0的正数,在64位浮点数体系中为5e-324),相应的,最接近0的负数为-Number.MIN_VALUE。
Number.MIN_VALUE; // 5e-324
- Number.MAX_SAFE_INTEGER:表示能够精确表示的最大整数,即9007199254740991。
Number.MAX_SAFE_INTEGER; // 9007199254740991
- Number.MIN_SAFE_INTEGER:表示能够精确表示的最小整数,即-9007199254740991。
Number.MIN_SAFE_INTEGER; // -9007199254740991
13.1 Number对象有4个实例方法,都跟将数值转换成指定格式有关。
- Number.prototype.toString() toString方法可以接受一个参数,表示输出的进制[2-36]。如果省略这个参数,默认将数值先转为十进制,再输出字符串;否则,就根据参数指定的进制,将一个数字转化成某个进制的字符串。具体见上文 进制转换。
10.5.toString(16); // a.8 10.5['toString'](16); // "a.8" 10..toString(16); // "a" 10.toString(16); // 报错
- Number.prototype.toFixed(num) toFixed方法的参数为指定的小数位数,有效范围为0到20,超出这个范围将抛出RangeError错误。ps:未报错,但是精度丢失。
(10).toFixed(2); // "10.00" (10.001).toFixed(2); // "10.00" (10.01).toFixed(21); // "10.009999999999999786837" 未报错,但是精度丢失 ?
- Number.prototype.toExponential() 参数为指定的小数位数,有效范围为0到20,超出这个范围将抛出RangeError错误。ps:未报错,但是精度丢失。
100..toExponential(); // "1e+2" 100..toExponential(1); // "1.0e+2" 100.1234.toExponential(); // "1.001234e+2" 100.1234.toExponential(2); // "1.001234e+2" 100.1234.toExponential(21); // "1.001234000000000037289e+2" 未报错,但是精度丢失 ?
- Number.prototype.toPrecision() toPrecision方法用于将一个数转为指定位数的有效数字。toPrecision方法的参数为有效数字的位数,范围是1到21,超出这个范围会抛出RangeError错误。
100..toPrecision(4); // "100.0" 100..toPrecision(5); // "100.00" 10120..toPrecision(4); // 1.012e+4 100123..toPrecision(2); // 1.0e+5
- toPrecision方法用于四舍五入时不太可靠,跟浮点数不是精确储存有关。
100123.35.toPrecision(7); // "100123.4" 10.35.toPrecision(3); // "10.3"
欢迎访问我的博客 Ama_zhe
--------内容系个人整理,如有错误,欢迎留言指出。谢谢!--------