0

IEEE-754 浮动可视化仪

准确了解十进制数字如何存储为 IEEE-754 浮点 — 符号位、指数位和尾数位 — 以及为什么不准确存储像 0.1 这样的数字。

Buy Me a Coffee at ko-fi.com
处理中... 0%
正火化
计算指数偏差
扩展尾数位
完成

结果

计算机存储的每个浮点数(JavaScript 数字、C 浮点数、Python 浮点数)在 IEEE 754 下都以相同的方式进行编码:一个符号位、一组指数位和一组尾数(分数)位。单精度(32位)使用1个符号位、8个指数位和23个尾数位;双精度(64 位)是几乎所有语言默认数字类型背后的格式,使用 1 个符号位、11 个指数位和 52 个尾数位。该工具获取您输入的任何十进制数字,使用浏览器自己的 DataView/ArrayBuffer 浮点编码器(与您的代码实际运行的机器相同的机器)以任一宽度对其进行编码,并根据其所属区域对每个位进行着色。

编码本身遵循三个步骤,该工具会遍历所有步骤,而不仅仅是显示最后的位。首先,标准化:数字被重写为 1.尾数 × 2^指数,在二进制小数点之前恰好有一个非零数字(数字太小而无法进行次正规化处理,没有隐式前导 1)。其次,指数偏差:由于指数字段必须将正指数和负指数都存储为无符号数,因此在以二进制写出字段之前添加固定偏差(单精度为 127,双精度为 1023)。第三,用经典的“乘以二,取整数部分作为下一位,保留余数”方法逐位扩展小数尾数 - 重复直到尾数字段已满,此时剩余的位决定结果是向上还是向下舍入(从一半到偶数,IEEE-754默认值)。

这正是像 0.1 这样普通的数字不能被准确存储的原因。在二进制中,0.1 是一个重复分数(0.0001100110011…,永远),因此没有有限的尾数可以精确地保存它 - 它必须在某个地方四舍五入。将 0.1 编码为 32 位浮点数并读回这些位,但您不会得到 0.1:您得到的正是 0.100000001490116119384765625。双精度还有 29 个尾数位可供使用,因此它的舍入误差要小得多,但它也不为零 - 64 位双精度数 0.1 正好是 0.1000000000000000055511151231257827021181583404541015625。该工具使用大整数算术(无浮点快捷方式)计算精确的存储值,因此您键入的内容与硬件实际保留的内容之间的差距永远不会被隐藏或近似。

特殊值得到精确的保留位模式,而不是普通编码:零和负零具有全零指数和尾数位(仅符号位不同),±Infinity具有全一指数位和全零尾数,NaN具有全一指数位和至少一个尾数位集。这里的所有内容都在您的浏览器中本地运行 - 您输入的任何内容都不会上传到任何地方 - 这使得这里成为构建浮点错误的真正直觉的安全场所:为什么几乎每种编程语言中都会出现“0.1 + 0.2 !== 0.3”,为什么图形代码中的 float32 纹理会丢失 float64 不会的精度,以及为什么金融代码通常应该完全避免二进制浮点。