JavaScript 整理笔记之数字详解

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
      

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
      
  • 进制转换
    • 十进制转其他 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
      

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
--------内容系个人整理,如有错误,欢迎留言指出。谢谢!--------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值