1.1 浮点数的舍入
浮点数在英语中称为 floating point number — 带小数点的数字:在美国,小数和整数部分由点分隔。这就是 float 名称的由来。
正如我们已经讨论过的,将浮点数 (float) 转换为整数 (int) 时,它总是向下舍入到整数 — 它的小数部分被忽略。但很容易想到一种情况,即需要将小数简单地舍入到最近的整数,或者向上舍入。怎么做呢?
对于这种情况,JavaScript 中有一个内置函数 round()。它甚至在创建 Math 库之前就被发明了,所以它不包括在其中。而用于向下和向上舍入的函数位于 math 库中。
Math.round() 函数
Math.round() 函数将数字舍入到最近的整数:
Math.round(浮点数)
此函数将返回最接近传入的浮点数的整数。
例子:
| 命令 | 结果 |
|---|---|
let x = Math.round(4.1); |
4 |
let x = Math.round(4.5); |
5 |
let x = Math.round(4.9); |
5 |
Math.ceil() 函数
Math.ceil() 函数将数字向上舍入到整数:
| 命令 | 结果 |
|---|---|
let x = Math.ceil(4.1); |
5 |
let x = Math.ceil(4.5); |
5 |
let x = Math.ceil(4.9); |
5 |
Math.floor() 函数
Math.floor() 函数将数字向下舍入到整数:
| 命令 | 结果 |
|---|---|
let x = Math.floor(4.1); |
4 |
let x = Math.floor(4.5); |
4 |
let x = Math.floor(4.9); |
4 |
如果你很难记住这些命令,一个小小的英语课程可能会帮你:
- math — 数学
- round — 圆/舍入
- ceiling — 天花板
- floor — 地板
1.2 浮点数的结构
JavaScript 中的 number 类型可以存储的值范围从 -1.7*10308 到 +1.7*10308。如此巨大的值范围是因为 number 类型的结构与整数类型完全不同。每个 number 类型的变量包含两个数字:第一个称为 尾数,第二个称为 指数。
假设我们有一个数字 123456789,并将其存储为 number 类型变量。然后这个数字将被转换为 1.23456789*108,在 number 类型中将存储数字 1.23456789 和 8。红色部分标出了“数字的有效部分”(尾数),蓝色部分表示指数。
这种方法可以存储非常大的数字和非常小的数字。但由于数字的大小限制为 8 个字节(64 位),部分位用于存储 指数(以及数字和指数的符号),尾数的最大长度限制为 15 个数字。
这是一种非常简化的浮点数结构描述:更详细的解释请参见 链接。
1.3 使用浮点数时的精度损失
使用浮点数时始终要记住,浮点数是不精确的。总会有 舍入误差、从十进制转换到二进制时的误差,以及最常见的情况 — 在相加/相减非常不同大小的数字时的精度损失。
最后一种情况对于编程新手来说是最意想不到的。
如果从数字 109 中减去 1/109,我们将再次得到 109。
| 减去不同大小的数字 | 解释 |
|---|---|
| 1000000000.000000000 - 0.000000001 1000000000.000000000 |
第二个数字太小,其有效部分被忽略(用灰色标出)。 红色标出了 15 个有效数字。 |
怎么说呢,编程和数学不完全一样。
1.4 比较浮点数的危险
当比较浮点数时,程序员会面临另一种危险。由于使用这些数字时可能会累积舍入误差,可能出现这样的情况,浮点数应该是相等的,但它们并不相等。反之亦然:数字应该不相等,但它们却相等。
例子:
| 命令 | 解释 |
|---|---|
let a = 1000000000.0let b = 0.000000001let c = a – b |
在变量 a 中将有值 1000000000.0。在变量 c 中将有值 1000000000.0(变量 b 中的数字太小)。 |
在上面的例子中,a 和 c 不应该相等,但它们相等。
或者我们来看另一个例子:
| 命令 | 解释 |
|---|---|
let a = 1.00000000000000001let b = 1.00000000000000002 |
在变量 a 中将有值 1.0。在变量 b 中将有值 1.0。 |
在实践中,浮点数比较是这样进行的:
如果数字的差(绝对值)小于某个非常小的数字,它们被认为是相等的。
例子:
let a = 0.00000000012;
let b = 0.000000000011;
if (Math.abs(a - b) < 0.00001) {
console.log("相等");
} else {
console.log("不相等");
}
GO TO FULL VERSION