各位观众,欢迎来到今天的JavaScript“数值大冒险”讲座!我是你们今天的向导,皮皮虾。今天咱们不聊框架,不谈架构,就聊聊JavaScript里的两个“数字公民”:Number
和 BigInt
。它们俩啊,就像一对性格迥异的兄弟,虽然都姓“数”,但脾气秉性可是大不相同。今天咱们就来扒一扒它们之间的爱恨情仇,看看怎么让它们和平共处,一起为我们的代码添砖加瓦。
第一幕:Number君的自白——“我可是老牌劲旅!”
Number
,这位老牌劲旅,在JavaScript里可是根深蒂固。它能表示整数、小数、正数、负数,甚至还能表示Infinity
(无穷大)和NaN
(Not a Number,不是一个数字)。
let age = 25; // 整数
let price = 99.99; // 小数
let pi = Math.PI; // 圆周率
let infinity = Infinity; // 无穷大
let notANumber = NaN; // 不是一个数字
Number
的优点在于它的广泛性和兼容性。几乎所有的JavaScript操作都默认使用 Number
。 但是,Number
也有它的局限性。 它使用IEEE 754双精度浮点数格式,这意味着它只能精确表示-2^53
到 2^53
之间的整数。一旦超出这个范围,就会出现精度丢失的问题。
console.log(9007199254740992); // 9007199254740992
console.log(9007199254740993); // 9007199254740992 咦?怎么一样了?
看到没?超过安全整数范围后,Number
就开始“睁眼说瞎话”了,明明是不同的数字,它却显示成一样的。 这就是精度丢失,在处理金融数据或者需要高精度计算的场景下,这可是要命的!
第二幕:BigInt君的登场——“我就是来解决问题的!”
为了解决 Number
的精度问题,ES2020 引入了 BigInt
。 BigInt
是一种新的原始类型,它可以表示任意精度的整数。 换句话说,只要你的内存足够大,BigInt
就能表示你想表示的任何整数。
创建 BigInt
有两种方式:
- 在整数后面加上
n
。 - 使用
BigInt()
构造函数。
let bigNumber1 = 123456789012345678901234567890n; // 使用 n 后缀
let bigNumber2 = BigInt(123456789012345678901234567890); // 使用 BigInt() 构造函数
let bigNumber3 = BigInt("123456789012345678901234567890"); // 也可以使用字符串
现在,我们再来试试之前 Number
无法精确表示的数字:
console.log(BigInt(9007199254740993)); // 9007199254740993n 终于正确了!
BigInt
就像一位救星,解决了 Number
的精度问题。 但是,BigInt
也不是万能的。 它不能直接和 Number
进行混合运算,而且不支持一些 Number
支持的操作,比如 Math.random()
。
第三幕:兄弟间的隔阂——“我们不能直接混合!”
Number
和 BigInt
就像是生活在不同世界的兄弟,它们不能直接进行混合运算。 如果你尝试这样做,JavaScript会毫不客气地抛出一个 TypeError
。
let number = 10;
let bigInt = 20n;
// console.log(number + bigInt); // TypeError: Cannot mix BigInt and other types, use explicit conversions
JavaScript 告诉你:“不能混合 BigInt
和其他类型,请使用显式转换。” 这就引出了我们今天的重点:显式转换。
第四幕:握手言和——显式转换的艺术
要让 Number
和 BigInt
和平共处,我们需要使用显式转换。 显式转换就像是兄弟俩之间的翻译,把一种语言翻译成另一种语言,让他们能够互相理解。
-
Number 转 BigInt:
可以使用
BigInt()
构造函数将Number
转换为BigInt
。 但是,需要注意的是,如果Number
不是一个整数,那么转换后的BigInt
会舍弃小数部分。let number = 10.5; let bigInt = BigInt(number); // 10n 注意:小数部分被舍弃了 console.log(bigInt);
请务必小心,因为这可能会导致数据丢失。
-
BigInt 转 Number:
可以使用
Number()
构造函数将BigInt
转换为Number
。 但是,需要注意的是,如果BigInt
的值超出了Number
的安全整数范围,那么转换后的Number
可能会失去精度。let bigInt = 9007199254740993n; let number = Number(bigInt); // 9007199254740992 精度丢失了! console.log(number);
所以,在将
BigInt
转换为Number
时,一定要谨慎,确保不会丢失精度。
第五幕:混合运算的正确姿势
有了显式转换,我们就可以让 Number
和 BigInt
进行混合运算了。 但是,我们需要记住一个原则: 先转换,再运算。
let number = 10;
let bigInt = 20n;
let result1 = Number(bigInt) + number; // 先将 bigInt 转换为 Number,再相加
console.log(result1); // 30
let result2 = bigInt + BigInt(number); // 先将 number 转换为 BigInt,再相加
console.log(result2); // 30n
选择哪种转换方式取决于你的具体需求。 如果你需要得到一个 Number
类型的结果,就将 BigInt
转换为 Number
; 如果你需要得到一个 BigInt
类型的结果,就将 Number
转换为 BigInt
。
第六幕:运算符的注意事项
BigInt
支持大部分常用的运算符,例如 +
、-
、*
、/
、%
等。 但是,有一些运算符需要特别注意:
-
除法
/
:BigInt
的除法会舍弃小数部分,只保留整数部分。 这与Number
的除法不同。console.log(10n / 3n); // 3n 小数部分被舍弃了 console.log(10 / 3); // 3.3333333333333335
-
位运算符:
BigInt
支持位运算符,例如&
、|
、^
、~
、<<
、>>
等。 这些运算符可以用于进行位操作。console.log(10n & 3n); // 2n console.log(10n | 3n); // 11n console.log(10n ^ 3n); // 9n console.log(~10n); // -11n console.log(10n << 2n); // 40n console.log(10n >> 2n); // 2n
-
比较运算符:
BigInt
可以使用比较运算符,例如==
、!=
、>
、<
、>=
、<=
等。 比较运算符可以用于比较BigInt
和Number
的大小。console.log(10n == 10); // true 注意:这里是 ==,不是 === console.log(10n === BigInt(10)); // true console.log(10n > 5); // true console.log(10n < 15); // true
需要注意的是,在使用
==
比较BigInt
和Number
时,JavaScript 会进行隐式类型转换。 为了避免意外的结果,建议使用===
进行严格比较。
第七幕:实际应用场景
BigInt
在很多场景下都非常有用,尤其是在需要处理大整数或者高精度计算的场景下。 举几个例子:
-
金融计算:
在金融计算中,精度至关重要。 使用
BigInt
可以避免因精度丢失而导致的错误。 -
密码学:
在密码学中,经常需要处理非常大的整数。 使用
BigInt
可以轻松地处理这些大整数。 -
科学计算:
在科学计算中,也经常需要处理高精度的数值。 使用
BigInt
可以满足这些需求。 -
ID 生成:
有些系统需要生成全局唯一的ID,可以使用
BigInt
来保证ID的唯一性,即使在高并发的情况下也不会出现重复。
第八幕:总结与建议
今天我们一起探索了 Number
和 BigInt
的特性、显式转换规则以及混合运算的注意事项。 让我们来总结一下:
Number
是JavaScript的老牌劲旅,但存在精度问题。BigInt
是JavaScript的新秀,可以表示任意精度的整数。Number
和BigInt
不能直接进行混合运算,需要使用显式转换。- 在进行显式转换时,需要注意可能出现的精度丢失问题。
BigInt
在金融计算、密码学、科学计算等领域有广泛的应用。
最后,给大家一些建议:
- 在选择使用
Number
还是BigInt
时,要根据具体的应用场景来决定。 如果不需要高精度,可以使用Number
; 如果需要高精度,就必须使用BigInt
。 - 在进行混合运算时,一定要使用显式转换,避免出现
TypeError
。 - 在将
BigInt
转换为Number
时,要注意可能出现的精度丢失问题。
好了,今天的“数值大冒险”讲座就到这里。 希望大家通过今天的学习,能够更好地理解和使用 Number
和 BigInt
,让它们在你的代码中发挥更大的作用! 感谢大家的观看,我们下次再见!