为什么不相等
从小我们就知道0.1 + 0.2=0.3
。但是,在光怪陆离的计算世界中,运算方式却大相径庭。
0.1加0.2为什么就不等于0.3呢?要回答这个问题,得先了解计算机内部是如何表示数的。
具体可以参考这这篇文章:为什么0.1加0.2不等于0.3呢?
如何解决
方法一
在JavaScript中的二进制的浮点数0.1和0.2并不是十分精确,在他们相加的结果并非正好等于0.3,而是一个比较接近的数字 0.30000000000000004
,所以条件判断结果为false
。
那么应该怎样来解决0.1+0.2
等于0.3呢? 最好的方法是设置一个误差范围值,通常称为”机器精度“,而对于Javascript来说,这个值通常是2^-52
,而在ES6
中, 已经为我们提供了这样一个属性:Number.EPSILON
,而这个值正等于2^-52
。这个值非常非常小,在底层计算机已经帮我们运算好,并且无限接近0,但不等于0,这个时候我们只要判断(0.1+0.2)-0.3
小于Number.EPSILON
,在这个误差的范围内就可以判定0.1+0.2===0.3
为true
。
Math.abs(0.1+0.2-0.3) < Number.EPSILON
但是这里要考虑兼容性的问题了,在chrome
中支持这个属性,但是IE
并不支持(我的版本是IE10
不兼容),所以我们还要解决IE
的不兼容问题:
Number.EPSILON = function () {
Number.EPSILON ? Number.EPSILON: Math.pow(2, -52);
}
方法二
将两边的参数值变成整数后进行比较
例:判断0.1+0.2和0.3是否相等,可将值扩大为1+2和3是否相等
js中如何处理bignum
在js中能表示最大整数是2的53次方,即9007199254740992
共16
位长度, js中内置了这个最大安全数字Number.MAX_SAFE_INTEGER
,
js实现两个大数相加:
function bigNum(x,y){
//截取参数16位后边的数字
let a=x.slice(16)*1;
let b =y.slice(16)*1;
//参数前16位的数字相加
let num=x.slice(0,16)*1+y.slice(0,16)*1;
//参数16位后边数字相加
let newNumber=a+b;
//判断16位后边数字的和大于最大数
if(newNumber>10000){
//前16位的数字+1,并截取16位后边的数字的第一位
let bigNumber=num+1+newNumber.toString().slice(1);
}else {
let bigNumber = num + newNumber.toString();
}
}
bigNum('12354675394563125395','63215635789621465129')
BigInt
BigInt
可能会成为自 ES2015
引入 Symbol
之后,增加的第一个新的内置类型。并且 BigInt
类型在 TypeScript3.2
版本被内置:
示例:
let max = Number.MAX_SAFE_INTEGER;
let a = max+1;
let b = max + 2;
console.log(a===b); // true
BigInt
使用:
let max = BigInt(Number.MAX_SAFE_INTEGER);
let a=max+1n;
let b = max + 2n;
console.log(a===b);//false
BigInt 可以表示任意大的整数。
语法:
BigInt(value);
除了通过BigInt
构造函数,我们还可以通过在一个整数字面量后面加n
的方式定义一个BigInt
,如:10n
。
类型判断:
typeof 1n === 'bigint'; // true
typeof BigInt('1') === 'bigint'; // true
Object.prototype.toString.call(10n) === '[object BigInt]'; // true
运算
以下操作符可以和BigInt
一起使用:+
、*
、-
、**
、%
、/
、>>>
(无符号右移)之外的 位操作 也可以支持。
当使用 BigInt 时,带小数的运算会被取整。
BigInt 和 Number 不是严格相等的,但是宽松相等的。
为了兼容asm.js
,BigInt
不支持单目(+)
运算符。