IEEE-754 标准和浮点数运算坑得要死
2023-11-18 01:48:36
前言
自从我开始学习计算机科学以来,就开始接触和学习浮点数,这已经有很多年了。当时,教授用了一个很形象的比喻来帮助我们理解浮点数的存储方式——“把小数点向左或向右移动一定位数”。举个例子,1.25可以表示为125 * 10 ^ -2,其中125是整数部分,-2是小数点移动的位数。这种表示方法与我们熟悉的十进制表示法很相似,很容易理解。
但是,计算机并不使用十进制表示浮点数,而是使用二进制。这使得浮点数的存储和运算变得更加复杂,也更容易出错。在本文中,我们将详细介绍IEEE-754标准,这是浮点数在计算机中存储和运算的标准。我们将讨论浮点数的表示方式、舍入误差以及如何比较两个浮点数。
一、IEEE-754 标准
IEEE-754 标准定义了浮点数的二进制表示方式。该标准最初于1985年发布,并于2008年进行了修订。IEEE-754 标准被广泛用于计算机、图形处理和数字信号处理等领域。
IEEE-754 标准中,浮点数由三个部分组成:符号位、指数和尾数。符号位表示数字是正数还是负数。指数表示数字的阶码,也就是小数点移动的位数。尾数表示数字的小数部分。
例如,十进制数1.25可以表示为二进制数1.01 * 2 ^ 0。符号位为0,表示数字是正数。指数为0,表示小数点没有移动。尾数为1.01,表示数字的小数部分是0.01。
二、舍入误差
由于计算机的有限精度,在浮点数运算中不可避免地会出现舍入误差。舍入误差是指在浮点数运算中,由于无法将结果精确表示为二进制数,而导致的结果与正确结果之间存在误差。
舍入误差通常很小,但在某些情况下可能会导致严重的后果。例如,在金融计算中,即使很小的舍入误差也可能导致巨大的损失。
三、比较两个浮点数
比较两个浮点数时,不能直接使用==运算符。这是因为浮点数的舍入误差可能会导致比较结果不正确。
比较两个浮点数的正确方法是使用Math.abs()函数计算两个浮点数之差的绝对值,然后将绝对值与某个小的阈值进行比较。如果绝对值小于阈值,则认为两个浮点数相等;否则,认为两个浮点数不相等。
例如,要比较两个浮点数1.0和1.0000000000000002,可以使用以下代码:
const a = 1.0;
const b = 1.0000000000000002;
const阈值 = 0.000000000000001;
if (Math.abs(a - b) < 阈值) {
console.log("a和b相等");
} else {
console.log("a和b不相等");
}
输出结果为:“a和b相等”。
总结
浮点数在计算机中存储和运算是一种非常复杂的事情。IEEE-754标准定义了浮点数的二进制表示方式,使得浮点数可以在计算机中进行存储和运算。但是,由于计算机的有限精度,在浮点数运算中不可避免地会出现舍入误差。舍入误差通常很小,但在某些情况下可能会导致严重的后果。因此,在进行浮点数运算时,需要特别注意舍入误差。