Skip to content

IEEE 754 浮点数转换器

在线 IEEE 754 浮点数转换器,支持半精度、单精度、双精度与 bfloat16,浮点数与十六进制/二进制互转。查看精确存储值、舍入误差与位布局,全部在浏览器本地完成,数据不上传。

无追踪 浏览器中运行 免费
所有计算均在你的浏览器本地完成——输入的数值不会离开这台设备。
格式
特殊值
位布局 — 点击任意位即可翻转
符号 指数 尾数
字段分解
符号
指数
尾数
存储值与舍入误差
你输入的值
实际存储的值
舍入误差
相邻可表示值
前一个
后一个
ULP(间距)
IEEE 754 各格式参数一览
格式 总位数 符号 指数 尾数 偏置 最大有限值 十进制位数
binary16 (FP16)1615101565504~3.3
bfloat1616187127≈3.39×10³⁸~2.3
binary32 (FP32)321823127≈3.40×10³⁸~7.2
binary64 (FP64)64111521023≈1.80×10³⁰⁸~15.9
已对照 IEEE 754-2019 格式定义核验数值准确性;所有示例值均经精确大整数运算验证 — Go Tools 工程团队 · 2026年7月16日

什么是 IEEE 754 浮点数?

IEEE 754 是定义计算机如何用二进制存储实数的标准。每个值被打包进三个字段:一个符号位、一个指数(以带偏置的形式存储,从而既能表示极大也能表示极小的数量级),以及一个保存有效数字的尾数。几乎所有 CPU、GPU 和编程语言都采用它,这也是为什么同样的舍入怪象会一模一样地出现在 JavaScript、Python、C 和 SQL 中。

关键在于:二进制浮点只能表示形如 m × 2ⁿ 的数。像 0.1 这样的十进制小数在二进制中是无限循环小数——0.000110011001100…——因此格式实际存储的是最接近的可表示邻居。单精度下这个邻居是 0.100000001490116119384765625;双精度下是 0.1000000000000000055511151231257827021181583404541015625。两者都不是 0.1。所有下游的怪现象——0.1 + 0.2 ≠ 0.3、求和漂移、相等判断失败——全都源自这一个事实,而本转换器把它变得可见:直接打印精确存储值,而不是舍入回去的近似值。

该标准还为特殊值保留了位模式。指数全 1 编码 ±Infinity(尾数为零)或 NaN(尾数非零);指数全 0 编码带符号零(尾数为零)或次正规数(尾数非零),后者以降低的精度填补紧邻零的下溢空隙。本工具覆盖的四种格式——binary16/FP16、bfloat16、binary32/FP32、binary64/FP64——区别仅在于各字段分到多少位:指数位越多范围越大,尾数位越多精度越高。机器学习偏爱的 bfloat16 其实就是把 FP32 的低 16 个尾数位截掉:范围相同,精度粗得多。

一个有用的心智模型是:可表示的浮点数在数轴上构成一张网格,其间距——最后一位上的一个单位,即 ULP——在每个 2 的幂处翻倍。在 1.0 附近,double 的网格间距约为 2.22 × 10⁻¹⁶;在 2⁵³ 附近则达到整整 1,这就是为什么 double 无法可靠地数到 2⁵³ 以上。本工具的相邻值面板直接展示这张网格:无论你输入什么值,都能看到它前后两个可表示值以及它们之间的精确间距。

// Float ↔ hex through the raw IEEE 754 bits (works in any browser / Node.js)
const buf = new DataView(new ArrayBuffer(8));

function floatToHex32(value) {
  buf.setFloat32(0, value); // rounds to nearest even
  return '0x' + buf.getUint32(0).toString(16).toUpperCase().padStart(8, '0');
}

function hexToFloat32(hex) {
  buf.setUint32(0, parseInt(hex, 16));
  return buf.getFloat32(0);
}

floatToHex32(0.1);        // '0x3DCCCCCD'
floatToHex32(3.14159);    // '0x40490FD0'
hexToFloat32('3DCCCCCD'); // 0.10000000149011612

核心特性

四种格式,一个视图

半精度(FP16)、bfloat16、单精度(FP32)、双精度(FP64)——一键切换,整页立即重新计算,几秒钟就能对比同一个数在各格式下的落点。

可点击的位网格

每一个位都是按钮。翻转符号位、微调指数、拨动某个尾数位,十进制、十六进制和二进制视图即刻更新——这是建立编码直觉最快的方式。

精确存储值,而非近似值

工具用精确的大整数运算算出所存位模式的完整十进制展开——double 下 0.1 的全部 55 位数字——并给出相对你输入值的精确带符号舍入误差。

相邻值与 ULP

查看当前数字前后两个可表示值,以及它们之间的精确间距(ULP)——正是这个网格间距决定了你在任意数量级上实际拥有多少精度。

特殊值一键直达

快捷按钮可载入所选格式的 ±0、±Infinity、NaN、最小次正规数和最大有限值,分类徽章会标明当前位模式编码的是什么。

可分享的永久链接,零上传

「复制链接」把格式和精确位模式编码进 URL——非常适合 bug 报告、代码评审和教学演示。一切都在你的浏览器中运行;你输入的任何内容都不会离开页面。

IEEE 754 转换示例

单精度下的 0.1 — 经典舍入误差

0.1
0x3DCCCCCD — 实际存储为 0.100000001490116119384765625

十进制 0.1 在二进制中没有有限表示,因此 IEEE 754 存储的是最接近的可表示值。在单精度(FP32)下这个值是 0x3DCCCCCD,即精确的 0.100000001490116119384765625——比 0.1 大约多出 1.49 × 10⁻⁹。本工具逐位展示这个精确存储值和精确误差,而不是编程语言打印回来的、已被舍入的「0.1」。仅这一个例子就能解释大多数浮点数怪象,包括为什么 0.1 + 0.2 不等于 0.3。

浮点数转十六进制:FP32 下的 3.14159

3.14159
0x40490FD0

在选中单精度(FP32)时输入 3.14159,十六进制框显示 0x40490FD0——符号位 0,偏置指数 128(即 2¹),尾数 0x490FD0。实际存储的值是 3.141590118408203125,比你输入的略大一点。十六进制形式正是你在网络抓包、GPU 缓冲区、寄存器视图和序列化二进制文件中看到的形式,而且转换是双向的:把 40490FD0 粘贴到十六进制框即可解码回来。

FP16 上限:65504 是半精度的尽头

65504
0x7BFF — FP16 最大的有限值

半精度只有 5 个指数位和 10 个尾数位,因此其最大有限值是 65504(0x7BFF)。输入 65520 或更大的数,结果就会舍入为 Infinity(0x7C00)——这是把机器学习模型量化到 FP16 时的真实隐患。切换到 bfloat16,同样的 65520 就能轻松容纳,因为 bfloat16 保留了 FP32 的 8 个指数位(范围),代价是放弃尾数位(精度)。这种取舍正是 ML 训练偏爱 bfloat16、而紧凑存储偏爱 FP16 的原因。

−0 与 +0:两种位模式,同一个值

-0
0x80000000(FP32),而 +0 是 0x00000000

IEEE 754 存在带符号的零:−0 只置符号位(FP32 下为 0x80000000),而 +0 是全零。它们在所有语言中比较相等,但 1/−0 得 −Infinity、1/+0 得 +Infinity,所以这个差异是可观察的。在工具中点击符号位即可在两者之间切换,你会看到分类徽章始终停在「零」上而十六进制值发生变化——一次点击就能说明为什么位级相等和数值相等是两回事。

如何转换 IEEE 754 浮点数

  1. 1

    选择浮点格式

    默认选中单精度(FP32)。处理 JavaScript/Python 风格的数字请切换到双精度(FP64);机器学习和图形领域常用的 16 位格式则选半精度(FP16)或 bfloat16。

  2. 2

    输入十进制数

    输入任意值——0.1、-2.5e3、65504——或使用特殊值快捷按钮载入 ±0、±Infinity、NaN、最小次正规数和最大有限值。转换随输入即时进行。

  3. 3

    阅读彩色标注的位布局

    符号位、指数字段和尾数以不同颜色高亮显示,字段分解表列出原始位、偏置运算过程和隐含前导位。

  4. 4

    查看精确存储值与误差

    精度面板打印出实际存储的值——每一位数字都经过精确计算——以及它与你输入值之间的舍入误差,还有前后两个相邻可表示值和 ULP 间距。

  5. 5

    翻转位、粘贴十六进制、复制结果

    点击任意位即可翻转,或粘贴十六进制(3DCCCCCD)和二进制位串解码回十进制。可复制十六进制、二进制、精确值,或复制一条能复现当前位模式的分享链接。

常见浮点数错误

相信打印值而不是存储值

语言打印浮点数时会舍入到能往返还原的最短字符串,所以 0.1 看起来干净利落,存储值却并非如此。判断精度要看精确展开,而不是 print() 显示了什么。

✗ 错误
print(0.1)  # 0.1 — 看起来精确,其实不是
✓ 正确
0.1 实际存储值(FP64)= 0.1000000000000000055511151231257827021181583404541015625

用精确相等比较浮点数

0.1 + 0.2 落在位模式 0x3FD3333333333334 上,而字面量 0.3 是 0x3FD3333333333333——相差一个 ULP,所以 == 为 false,尽管两者打印出来都像 0.3。

✗ 错误
if (0.1 + 0.2 === 0.3) { … }   // 永远不会执行
✓ 正确
if (Math.abs(a - b) < 1e-9) { … }   // 按你的数据量级选定容差

量化到 FP16 前不检查范围

FP16 的最大有限值是 65504。任何更大的数都会变成 Infinity,而 Infinity 一旦进入计算就会传播。向下转换前先检查最大值——或者改用保留 FP32 范围的 bfloat16。

✗ 错误
fp16(65520)   → Infinity (0x7C00) — 静默溢出
✓ 正确
bf16(65520)   → 有限值(bfloat16 保留 8 个指数位)

用相等判断测试 NaN

NaN 是唯一不等于自身的值——这是有意的设计,让失败的计算无法伪装成正常数字。请使用语言提供的 isNaN 检查而不是 ==,并记住存在数以百万计的不同 NaN 位模式。

✗ 错误
if (x === NaN) { … }        // 永远为 false,即使 x 就是 NaN
✓ 正确
if (Number.isNaN(x)) { … }  // 正确的检测方式

IEEE 754 转换器能做什么

调试序列化的二进制数据
把在网络抓包、GPU 缓冲区、寄存器转储或文件格式中找到的十六进制值粘贴进来,解码出精确的十进制值——也可以反向转换来编写测试夹具。字节序提示:所显示的十六进制是大端(big-endian)位模式;如果你的转储是小端序(little-endian),粘贴前请先反转字节顺序。
理解 ML 量化
检查你的数值能否扛过 FP16 的 65504 上限,逐位对比 FP16 与 bfloat16 的精度损失,并检视梯度会发生下溢的次正规数区间。
解释浮点数 bug
当同事问为什么两个「相等」的数不一样时,发一条永久链接,同时展示两个位模式和精确存储值——争论自然平息。更长的数据转储可搭配文本对比工具使用。
学习或讲授编码格式
当学生可以亲手点击指数位、看着偏置运算实时更新时,计算机体系结构课程就变得具体了。字段分解表的画法与教科书中的格式示意图一致。
解码嵌入式与工业寄存器
Modbus、CAN 和传感器载荷经常以原始十六进制字的形式携带 FP32 值。把该字粘贴到这里即可读出物理量,无需另写临时脚本。

IEEE 754 格式与特殊值

四种二进制格式一览
binary16(FP16):1 符号位 + 5 指数位 + 10 尾数位,偏置 15,最大值 65504,约 3.3 位十进制数字。bfloat16:1 + 8 + 7,偏置 127,最大值 ≈ 3.39 × 10³⁸,约 2.3 位。binary32(FP32):1 + 8 + 23,偏置 127,最大值 ≈ 3.40 × 10³⁸,约 7.2 位。binary64(FP64):1 + 11 + 52,偏置 1023,最大值 ≈ 1.80 × 10³⁰⁸,约 15.9 位。规律很清楚:指数位换范围,尾数位换精度,而 bfloat16 刻意用全部精度优势换取 FP32 的范围。
值是如何组装出来的
正规数的解码公式是 (−1)^sign × 1.mantissa × 2^(exponent − bias)。前导 1 是隐含的——它不被存储,这就是 23 位尾数字段能提供 24 位精度的原因。存储的指数等于真实指数加偏置(FP32 为 127),因此 2⁰ 存储为 01111111。本工具的字段分解表会针对当前值逐步展示这套运算。
特殊值:被保留的指数模式
指数全 1 且尾数为零是 ±Infinity;尾数非零则是 NaN(规范的 quiet NaN 会置上尾数的最高位)。指数全 0 且尾数为零是 ±0;尾数非零则是次正规数,按 0.mantissa × 2^(1 − bias) 解码——没有隐含前导 1。这些规则在四种格式中完全一致,所以同一组快捷值在每种格式下都能用。
舍入:就近舍入,平局取偶
当一个值落在两个可表示数之间时,IEEE 754 的默认模式舍入到较近的那个;恰好在正中间时,取尾数最后一位为 0 的那个(平局取偶),以避免系统性漂移。本转换器把你的十进制输入收窄到目标格式时应用的正是这条规则,误差面板会精确显示由此产生的带符号差值。
ULP:浮点数的网格间距
可表示的浮点数并非均匀分布——相邻值之间的间距(最后一位上的一个单位)在每个 2 的幂处翻倍。在 1.0 附近,double 的 ULP 是 2⁻⁵² ≈ 2.22 × 10⁻¹⁶;到 2⁵³ 附近 ULP 达到 1.0,整数开始被跳过。相邻值面板会精确打印当前的 ULP——这才是「我的数字在这里有多精确?」的诚实答案。

浮点数最佳实践

永远不要用 == 比较浮点数
任何运算之后,两个数学上相等的表达式都可能相差一个 ULP。请使用与数量级匹配的容差来比较——或者统计两个位模式之间相差多少个 ULP,本工具可以直接查看。
别把金额放进二进制浮点数
没有任何 2 的幂网格能精确容纳 0.10,用浮点数存货币会累积出肉眼可见的误差。请改用整数(分)或十进制类型;本页的精确存储值面板就是长期有效的证据。
按范围而非习惯选择 16 位格式
如果你的值可能超过 65504——损失函数、梯度、物理量尖峰——FP16 会溢出为 Infinity,而 bfloat16 安然无恙。如果所有值都被归一化到窄区间,FP16 多出的尾数位能带来明显更好的精度。
收窄转换时当心双重舍入陷阱
在罕见的中点情形下,十进制 → double → half 的转换结果可能与十进制 → half 直接转换相差一个 ULP。本工具把你的十进制输入一步舍入到目标格式,所以你看到的就是诚实的 IEEE 754 答案。
预期整数在 2⁵³ 之上会失真
double 能精确存储到 2⁵³ 为止的每一个整数,之后开始跳数——2⁵³ + 1 无法表示。若你处理的 ID 或计数器接近该量级,请使用 64 位整数或字符串,并把可疑值放到这里做位级检查。

IEEE 754 转换器常见问题

为什么 0.1 + 0.2 不等于 0.3?
因为这三个数在二进制浮点中都不存在。double 把 0.1 存储为精确的 0.1000000000000000055511151231257827021181583404541015625,0.2 也带有类似的微小超量;两者相加得到 0.3000000000000000444089209850062616169452667236328125(位模式 0x3FD3333333333334),而字面量 0.3 舍入为 0.299999999999999988897769753748434595763683319091796875(位模式 0x3FD3333333333333)。相加的结果比字面量高出一个可表示步长——两种不同的位模式——所以 0.1 + 0.2 == 0.3 在每一种 IEEE 754 语言中都是 false:JavaScript、Python、Java、C、Rust、Go 无一例外。在本转换器中输入 0.1,读一读精确存储值,你就能亲眼看到问题的根源。
什么是 IEEE 754?
IEEE 754 是二进制浮点运算的技术标准,几乎所有现代 CPU、GPU 和编程语言都在使用它。该标准定义了数字如何被打包成位——一个符号位、一个指数字段和一个尾数(有效数字)——以及舍入规则和特殊值 Infinity、NaN、带符号零与次正规数。实践中你会遇到的格式有 binary32(float,FP32)、binary64(double,FP64)、binary16(half,FP16),以及机器学习中使用的相关截断格式 bfloat16。本转换器在位级别展示全部四种格式。
FP16 和 bfloat16 有什么区别?
两者都是 16 位格式,但位的分配方式不同。FP16(IEEE binary16)使用 5 个指数位和 10 个尾数位:精度更高,但范围极小——最大有限值只有 65504,溢出到 Infinity 是常态隐患。bfloat16 保留了 FP32 的 8 个指数位、只留 7 个尾数位:拥有 float 完整的 ±3.4 × 10³⁸ 范围,但精度粗糙得多。这就是为什么梯度可能远超 65504 的 ML 训练把 bfloat16 定为标准,而数值可控的存储与推理场景更适合 FP16。在这里可以直接对比:输入 0.1 再切换格式——FP16 存储 0.0999755859375(0x2E66),bfloat16 存储 0.10009765625(0x3DCD)。
什么是次正规数(subnormal / denormal)?
当指数字段全为零时,IEEE 754 会去掉隐含的前导 1,让尾数逐渐向零收缩——这就是次正规数(旧称 denormal,非规格化数)。它们填补了零与最小正规数之间的空隙,使两个不相等浮点数的差值永远不会被舍入为零(渐进下溢)。代价是精度降低,并且在许多 CPU 上运算更慢。FP16 中最小的次正规数是 2⁻²⁴ = 0.000000059604644775390625;在任意格式下点击「最小次正规数」快捷值即可查看它的位模式——指数位全零,尾数为 0…001。
该用 float 还是 double?
除非有实测的理由,否则默认用 double(FP64)。double 大约有 15–16 位有效十进制数字,float 大约只有 7 位,而且多数语言(JavaScript 的 number、Python 的 float)本来就只有 double。当内存带宽或存储占主导时——大数组、GPU 流水线、图形——并且你已确认 7 位数字够用,再选 float(FP32)。至于金额,请改用整数(分)或十进制类型:没有任何二进制格式能精确存储 0.1,本工具的存储值面板就是明证。如需查看整数进制,请使用进制转换器
如何手工把浮点数转成十六进制?
先取符号(正数为 0,负数为 1)。把绝对值写成二进制,并规格化为 1.xxx × 2ⁿ。将 n 加上该格式的偏置(FP32 为 127,FP64 为 1023),写入指数位。去掉前导 1,保留小数部分接下来的 23(或 52)位作为尾数,在截断处按「就近舍入、平局取偶」处理。把符号、指数、尾数拼接起来,每 4 位组成一个十六进制数字。以 FP32 下的 3.14159 为例,得到 0 | 10000000 | 10010010000111111010000 → 0x40490FD0——或者跳过这些手工计算,让本转换器把每一步可视化地展示给你。
使用这个转换器时我的数据会被上传吗?
不会。每一次转换都在你的浏览器本地用纯 JavaScript 完成——依靠 DataView 和 BigInt 运算,没有服务器往返,也没有第三方库。你可以打开浏览器开发者工具,边输入边观察网络面板保持静默,甚至完全断网继续转换。「复制链接」按钮把位模式编码进 URL 片段(fragment),它同样不会发送到任何服务器。