Number 数字

重要通知

基本概况

Number对象

根据语言规范,JavaScript 采用“遵循 IEEE 754 标准的双精度 64 位格式”("double-precision 64-bit format IEEE 754 values")表示数字。在JavaScript(除了BigInt)当中,并不存在整数/整型(Integer)。

注意事项

安全整数表示在 JavaScript 中能够精确表示的整数,安全整数的范围在 2 的 -53 次方到 2 的 53 次方之间(不包括两个端点),超过这个范围的整数无法精确表示,即数字有效范围为10^(-308) - 10^(308)之间。(9007 1992 5474 0991 - -9007 1992 5474 0991)

常量

  • Number.EPSILON:表示 1 与Number可表示的大于 1 的最小的浮点数之间的差值。
  • Number.MAX_SAFE_INTEGER:最大的安全整数 (2^53 - 1),即9007 1992 5474 0991。
  • Number.MIN_SAFE_INTEGER:最小的安全整数 (-(2^53 - 1)),即-9007 1992 5474 0991。
  • Number.MAX_VALUE:能表示的最大正数,MAX_VALUE 属性值接近于 1.7976931348623157e+308。大于 MAX_VALUE 的值代表 "Infinity"。 -Infinity > Number.MAX_VALUE
  • Number.MIN_VALUE:能表示的最小正数即最接近 0 的正数 (实际上不会变成 0),即5e-324,小于 MIN_VALUE 的值代表 "-Infinity"。-Infinity < Number.MIN_VALUE
  • Number.NaN:特殊的“非数字”值。
  • Number.NEGATIVE_INFINITY:特殊的负无穷大值,在溢出时返回该值。
  • Number.POSITIVE_INFINITY:特殊的正无穷大值,在溢出时返回该值。

核心方法

  • number.toPrecision(x):指定精度的数字格式,x为指定的数字格式长度。
(1.335).toPrecision(20);    // 输出:"1.3349999999999999645"

浮点数精度问题

注意JavaScript的安全数值区间为(Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER),因此超出该安全数值范围外的值会被影响,即产生浮点数精度问题。

console.log(0.1 + 0.2);  // 输出:0.30000000000000004

解决方案:把浮点数转化为字符串,模拟实际运算的过程,例如采用第三方bignumber.js,decimal.js,以及big.js库等,这些库不仅解决了浮点数的运算精度问题,还支持了大数运算,并且修复了原生toFixed结果不准确的问题。

大数精度问题

// 9999 9999 9999 9999
console.log(9999999999999999); // 输出:1 0000 0000 0000 0000

四舍五入问题

JavaScript中四舍五入都是五(不包含五)以上入,反之则舍。

console.log(1.335.toFixed(2)); // 输出:1.33
console.log(Math.ceil(1.5)); // 输出:2
console.log(Math.floor(1.5)); // 输出:1

基础属性与方法

精度实现问题

精度误差示例

基础类库

Number(数值)

JavaScript 能够准确表示的整数范围在-2^53到2^53之间(不含两个端点),超过这个范围,无法精确表示这个整数。 JS 中能精准表示的最大整数是 Math.pow(2, 53) 在JavaScript中数字不区分整型和浮点型,所有数字以浮点型表示; 数字有效范围为10^(-308) - 10^(308)之间; 当在JS中使用的数字大于JS所能表示的最大值时,JS就会将其输出Infinity,即无限大;反之,JS所使用的数字小于JS所能表示的最小值时,输出-Infinity。

JS 四舍五入

  var num =2.446242342;
  num = Math.round((num + Number.EPSILON) * 100) / 100;  // 输出结果为 2.45

NaN:Not a Number 的缩写

即"不是一个数字Number"的意思,通常在进行数学运算时产生了未知的结果或错误,JS就会返回NaN。 (用0来除以0,JS就会返回NaN);在JS中使用isNaN()函数来判断运算结果是不是NaN。

精度

整数(不使用小数点或指数计数法)最多为 15 位

安全整数

安全整数表示在 JavaScript 中能够精确表示的整数,安全整数的范围在 2 的 -53 次方到 2 的 53 次方之间(不包括两个端点),超过这个范围的整数无法精确表示。

最大/最小安全整数

最大安全整数:安全整数范围的上限,即 2 的 53 次方减 1(9007 1992 5474 0991) 最小安全整数:安全整数范围的下限,即 2 的 53 次方减 1 的负数(-9007 1992 5474 0991)

特殊值

Infinity:数字超过数字上限(溢出),会被显示为无穷大(infinity)值;反之,结果为负无穷大,以-Infinity表示 NaN:

方法


toExponential() 可把对象的值转换成指数计数法 1000.toExponential(1) 1.0e+4 toFixed() 可把 Number 四舍五入为指定小数位数的数字 toPrecision() 把数字格式化为指定的长度 13.3714.toPrecision(3) 13.4 toString() 可以使用 toString() 方法 输出16进制、8进制、2进制 valueOf() 返回一个 Number 对象的基本数字值

[number].toFixed()

let result = 23.786; console.log(result.toFixed()); //24 console.log(result.toFixed(2)); //23.79

Number.isFinite()

用于检查一个数值是否为有限的( finite ),即不是 Infinity console.log( Number.isFinite(1)); // true console.log( Number.isFinite(0.1)); // true

NaN 不是有限的

  console.log( Number.isFinite(NaN)); // false
  console.log( Number.isFinite(Infinity));  // false
  console.log( Number.isFinite(-Infinity)); // false

Number.isNaN()

用于检查一个值是否为 NaN Number.isNaN() 不存在隐式的 Number() 类型转换,非 NaN 全部返回 false

  console.log(Number.isNaN(NaN));      // true
  console.log(Number.isNaN('true'/0)); // true
  console.log(Number.isNaN(111));      // false
  /**
   * Number.parseInt(string[, radix])
   * string:要解析的值。 如果此参数不是字符串,则使用ToString抽象操作将其转换为字符串。忽略此参数中的前导空格。
   * radix:一个介于2到36之间的整数,代表字符串的基数(数学数字系统中的基)。小心-这并不是默认为10。
   */
  Number.parseInt('12.34'); // 12
  Number.parseInt(12.34);   // 12
  Number.parseInt('0011', 2); // 3
  // 与全局的 parseInt() 函数是同一个函数
  Number.parseInt === parseInt; // true
  /**
   * Number.parseFloat()
   * 用于把一个字符串解析成浮点数, 整数和浮点数采用的是同样的储存方法,因此 1 与 1.0 被视为相同的值
   */
  Number.isInteger(1);   // true
  Number.isInteger(1.0); // true
  Number.isInteger(1.1);     // false
  Number.isInteger(Math.PI); // false  

Number.isInteger:数值的精度超过 53 个二进制位时,由于第 54 位及后面的位被丢弃,会产生误判

  Number.isInteger(1.0000000000000001) // true
  // 一个数值的绝对值小于 Number.MIN_VALUE(5E-324),即小于 JavaScript 能够分辨的最小值,会被自动转为 0,也会产生误判
  Number.isInteger(5E-324); // false
  Number.isInteger(5E-325); // true  
  /**
   * Number.isSafeInteger()
   * 用于判断数值是否在安全范围内
   */
  Number.isSafeInteger(Number.MIN_SAFE_INTEGER - 1); // false
  Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1); // false  

  console.log(Number.MAX_VALUE); // 1.7976931348623157e+308
  console.log(Number.MIN_VALUE); // 5e-324
  // 除数
  console.log(10/0);    //Infinity
  console.log(10/0.0);  //Infinity  

ES6语法

Use 0b prefix for binary, and 0o prefix for octal integer literals
Number.isNaN(): Number.isFinite():
Number.parseInt(): Number.parseFloat(): Number.isInteger(): Number.isSafeInteger():

常量

Number.EPSILON:表示 1 与Number可表示的大于 1 的最小的浮点数之间的差值。
Number.MAX_SAFE_INTEGER:最大的安全整数 (2^53 - 1) Number.MIN_SAFE_INTEGER:最小的安全整数 (-(2^53 - 1)) Number.MAX_VALUE:能表示的最大正数,MAX_VALUE 属性值接近于 1.7976931348623157e+308。大于 MAX_VALUE 的值代表 "Infinity"。 -Infinity > Number.MAX_VALUE Number.MIN_VALUE:能表示的最小正数即最接近 0 的正数 (实际上不会变成 0),即5e-324,小于 MIN_VALUE 的值代表 "-Infinity"。-Infinity < Number.MIN_VALUE Number.NaN:特殊的“非数字”值。 Number.NEGATIVE_INFINITY:特殊的负无穷大值,在溢出时返回该值。 Number.POSITIVE_INFINITY:特殊的正无穷大值,在溢出时返回该值。

浮点计算与精度误差

误差原理

JavaScript的数字都遵循IEEE 754标准构建,在内部都是64位浮点小数表示

解决方案

  • https://www.runoob.com/w3cnote/js-precision-problem-and-solution.html

Number.EPSILON 属性:表示 1 与Number可表示的大于 1 的最小的浮点数之间的差值。 Number.EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16,或者 2-52。

JavaScript的数字都遵循IEEE 754标准构建,在内部都是64位浮点小数表示

JavaScript中的数字是如何编码的: https://2ality.com/2012/04/number-encoding.html toFixed()和toPrecision()

0.1 + 0.2 === 0.3 // is false    因为0.1+0.2等于0.30000000000000004
9007199254740992 + 1 // is equal to 9007199254740992
9007199254740992 + 2 // is equal to 9007199254740994

Number类型最大限制:16位

最大值:9007199254740992,超过之后会发生失真

  console.log(9007199254740990);      //9007199254740990
  console.log(9007199254740991);      //9007199254740991 
  console.log(9007199254740992);      //9007199254740992  
  console.log(9007199254740993);      //9007199254740992
  
  console.log(9007199254740992 + 1);  //9007199254740992
  console.log(9007199254740992 + 2);  //9007199254740994
  console.log(9007199254740992 + 3);  //9007199254740996
  console.log(9007199254740992 + 4);  //9007199254740996
  console.log(9007199254740992 + 5);  //9007199254740996
  console.log(9007199254740992 + 6);  //9007199254740998
  console.log(9007199254740992 + 7);  //9007199254741000
  console.log(9007199254740992 + 8);  //9007199254741000
  console.log(9007199254740992 + 9);  //9007199254741000
  console.log(9007199254740992 + 10); //9007199254741002  

解决方案

将数字转换为字符串处理

  console.log(0.1 + 0.2);           // 0.30000000000000004
  console.log(parseInt(0.000006));  // 0
  console.log(parseInt(0.000001));  // 0
  console.log(parseInt(0.0000001)); // 1
  console.log(parseInt(0.0000008)); // 8  

代码示例

  console.log(999999999999999);   //999999999999999
  console.log(9999999999999999);  //10000000000000000
  console.log(1000000000000001);  //1000000000000001  

解决方案

toFixed()和toPrecision() node-bignum

输入框,限制整数位、小数位

function inputLimitIntegerDecimal(integerLength, decimalLength) {
  const regExp = new RegExp(`^\\D*(\\d{${integerLength}}(?:\\.\\d{0,${decimalLength}})?).*$`, 'g')
}








Last Updated:
Contributors: 709992523, Eshen