数字类型
编写数字的方法
表示十个亿很显然我们可以写成
let billion = 1000000000;
当然加上下划线作为分隔符也可以方便我们的阅读;JavaScript 引擎会直接忽略数字之间的 _
let billion = 1_000_000_000;
不过我们是懒的,在 JavaScript 中,我们可以通过在数字后面附加字母 "e" 并指定零的个数来缩短数字:
let billion = 1e9; // 10 亿,字面意思:数字 1 后面跟 9 个 0
alert( 7.3e9 ); // 73 亿(与 7300000000 和 7_300_000_000 相同)
同样我们可以用附加字母 "e" 写一个很小的数字let mcs = 1e-6; 表示 1 的左边有 6 个 0
Number.prototype.toString()
语法:numObj.toString([radix])
radix: 指定要用于数字到字符串的转换的基数 (从 2 到 36)。如果未指定 radix 参数,则默认值为 10。
如果转换的基数大于 10,则会使用字母来表示大于 9 的数字,比如基数为 16 的情况,则使用 a 到 f 的字母来表示 10 到 15。
如果基数没有指定,则使用 10。
如果对象是负数,则会保留负号。即使 radix 是 2 时也是如此:返回的字符串包含一个负号(-)前缀和正数的二进制表示,不是 数值的二进制补码。
进行数字到字符串的转换时,建议用小括号将要转换的目标括起来,防止出错。
🐱👓示例:
console.log((254).toString(16)); //fe
console.log((259).toString(16)); //103
console.log((254).toString(2));//11111110
“fe”的原因是16进制,e代表14 ,f是15,15*16=240 再加上14 结果为254
“11111110”是使用二进制的结果
那么试试36进制吧~
console.log( 123456..toString(36) ); // 2n9c
👀使用两个点来调用一个方法:
请注意
123456..toString(36)中的两个点不是打错了。如果我们想直接在一个数字上调用一个方法,比如上面例子中的toString,那么我们需要在它后面放置两个点..。 如果我们放置一个点:123456.toString(36),那么就会出现一个 error,因为 JavaScript 语法隐含了第一个点之后的部分为小数部分。如果我们再放一个点,那么 JavaScript 就知道小数部分为空,现在使用该方法。 也可以写成(123456).toString(36)。
舍入
舍入(rounding)是使用数字时最常用的操作之一。
这里有几个对数字进行舍入的内建函数:
Math.floor
向下舍入:`3.1` 变成 `3`,`-1.1` 变成 `-2`。
Math.ceil
向上舍入:`3.1` 变成 `4`,`-1.1` 变成 `-1`。
Math.round
向最近的整数舍入:`3.1` 变成 `3`,`3.6` 变成 `4`,中间值 `3.5` 变成 `4`。
Math.trunc(IE 浏览器不支持这个方法)
移除小数点后的所有内容而没有舍入:`3.1` 变成 `3`,`-1.1` 变成 `-1`。
但是如果我们有个需求是想要舍入到小数点后两位怎么办?
乘除法
先让他乘100而后除回
let num = 1.23456;
alert( Math.round(num * 100) / 100 ); // 1.23456 -> 123.456 -> 123 -> 1.23
函数toFixed(n)
函数toFixed(n)将数字舍入到小数点后 n 位,并以字符串形式返回结果。
console.log((12.315).toFixed(1)); // "12.3"
详细点:
var numObj = 12345.6789;
numObj.toFixed(); // 返回 "12346":进行四舍六入五看情况,不包括小数部分
numObj.toFixed(1); // 返回 "12345.7":进行四舍六入五看情况
numObj.toFixed(6); // 返回 "12345.678900":用 0 填充
(1.23e+20).toFixed(2); // 返回 "123000000000000000000.00"
(1.23e-10).toFixed(2); // 返回 "0.00"
2.34.toFixed(1); // 返回 "2.3"
2.35.toFixed(1) // 返回 '2.4'. Note it rounds up
2.55.toFixed(1) // 返回 '2.5'. Note it rounds down - see warning above
-2.34.toFixed(1); // 返回 -2.3(由于操作符优先级,负数不会返回字符串)
(-2.34).toFixed(1); // 返回 "-2.3"(若用括号提高优先级,则返回字符串)
由于操作符优先级,负数不会返回字符串;若用括号提高优先级,则返回字符串
parseInt 和 parseFloat
使用加号 + 或 Number() 的数字转换是严格的。如果一个值不完全是一个数字,就会失败:
alert( +"100px" ); // NaN
唯一的例外是字符串开头或结尾的空格,因为它们会被忽略。
但在现实生活中,我们经常会有带有单位的值,例如 CSS 中的 "100px" 或 "12pt"。并且,在很多国家,货币符号是紧随金额之后的,所以我们有 "19€",并希望从中提取出一个数值。
这就是 parseInt 和 parseFloat 的作用。
它们可以从字符串中“读取”数字,直到无法读取为止。如果发生 error,则返回收集到的数字。函数 parseInt 返回一个整数,而 parseFloat 返回一个浮点数:
alert( parseInt('100px') ); // 100
alert( parseFloat('12.5em') ); // 12.5
alert( parseInt('12.3') ); // 12,只有整数部分被返回了
alert( parseFloat('12.3.4') ); // 12.3,在第二个点出停止了读取
alert( parseInt('a123') ); // NaN,第一个符号停止了读取
第一个符号停止了读取后,parseInt/parseFloat 会返回 NaN
parseInt(str, radix) 的第二个参数
parseInt()函数具有可选的第二个参数。它指定了数字系统的基数,因此parseInt还可以解析十六进制数字、二进制数字等的字符串:
alert( parseInt('0xff', 16) ); // 255
alert( parseInt('ff', 16) ); // 255,没有 0x 仍然有效
alert( parseInt('2n9c', 36) ); // 123456
警告:parseInt 将 BigInt 转换为 Number,并在这个过程中失去了精度。这是因为拖尾的非数字值,包括 "n",会被丢弃。
注意
在内部,数字是以 64 位格式 IEEE-754 表示的,所以正好有 64 位可以存储一个数字:其中 52 位被用于存储这些数字,其中 11 位用于存储小数点的位置,而 1 位用于符号。
如果一个数字真的很大,则可能会溢出 64 位存储,变成一个特殊的数值 Infinity就会导致精度的损失
浮点数(float)不能精确地用二进制表示所有小数。这可能会导致意外的结果,例如 0.1 + 0.2 === 0.3 返回 fals
什么是
0.1?0.1就是1除以10,1/10,即十分之一。在十进制数字系统中,这样的数字表示起来很容易。将其与三分之一进行比较:1/3。三分之一变成了无限循环小数0.33333(3)。在十进制数字系统中,可以保证以
10的整数次幂作为除数能够正常工作,但是以3作为除数则不能。也是同样的原因,在二进制数字系统中,可以保证以2的整数次幂作为除数时能够正常工作,但1/10就变成了一个无限循环的二进制小数。
使用二进制数字系统无法 精确 存储 0.1 或 0.2,就像没有办法将三分之一存储为十进制小数一样。
解决办法: 最可靠的方法是借助方法toFixed(n)对结果进行舍入,注意乘/除法可以减少误差,但不能完全消除误差。