C++17 十六进制浮点字面量

2026年7月13日 Crystal-Sky 3 min read C++C++17基础语法浮点数字面量

回顾普通浮点字面量

平时常见的浮点字面量使用十进制表示:

double a = 3.14;
double b = 1.5e2;   // 1.5 × 10^2 = 150
double c = 2.5e-3;  // 2.5 × 10^-3 = 0.0025

其中:

  • eE 表示十进制指数;
  • 指数部分的底数是 10。

十六进制浮点字面量

C++17 支持直接书写十六进制浮点字面量。

基本形式为:

0x十六进制有效数字p二进制指数

例如:

double x = 0x1.8p1;

它表示:

\[ 0x1.8 \times 2^1 \]

这里需要注意:

  • 前缀使用 0x0X
  • 有效数字使用十六进制;
  • 指数标记必须使用 pP
  • 指数的底数是 2,而不是 10。

为什么指数用 p

十六进制数字中,字母 e 本身就是合法数字:

0x1e

这里的 e 表示十六进制数字 14。

因此,十六进制浮点数不能再使用 e 表示指数,只能使用 pP

计算示例

0x1p0

double x = 0x1p0;

表示:

\[ 1 \times 2^0 = 1 \]

所以 x 的值为 1。

0x1p3

double x = 0x1p3;

表示:

\[ 1 \times 2^3 = 8 \]

0x1.8p1

十六进制小数:

\[ 0x1.8 = 1 + \frac{8}{16} = 1.5 \]

因此:

\[ 0x1.8p1 = 1.5 \times 2^1 = 3 \]
double x = 0x1.8p1;  // 3.0

0x1.4p2

先计算有效数字:

\[ 0x1.4 = 1 + \frac{4}{16} = 1.25 \]

再乘以二进制指数:

\[ 1.25 \times 2^2 = 5 \]
double x = 0x1.4p2;  // 5.0

负指数

double x = 0x1p-2;

表示:

\[ 1 \times 2^{-2} = \frac{1}{4} = 0.25 \]

类型后缀

十六进制浮点字面量也可以使用浮点类型后缀。

auto a = 0x1.8p1;   // double
auto b = 0x1.8p1f;  // float
auto c = 0x1.8p1L;  // long double

规则与普通浮点字面量一致:

后缀类型
无后缀double
fFfloat
lLlong double

与普通浮点写法对比

写法含义结果
1.5e2\(1.5 \times 10^2\)150
0x1.8p1\(1.5 \times 2^1\)3
0x1p4\(1 \times 2^4\)16
0x1p-3\(1 \times 2^{-3}\)0.125

为什么有这种写法

计算机中的浮点数通常采用二进制表示。

十进制小数有时不能被二进制精确表示,例如:

double x = 0.1;

而十六进制浮点字面量与二进制浮点表示关系更直接。

例如:

double x = 0x1p-3;

它准确表示:

\[ 2^{-3} = 0.125 \]

因此十六进制浮点字面量常用于:

  • 精确表示二进制浮点值;
  • 浮点算法测试;
  • 底层数值程序;
  • 需要明确控制浮点常量的场景。

常见错误

使用 e 表示指数

错误:

double x = 0x1.8e2;

在十六进制中,e 会被当作数字的一部分。

正确写法:

double x = 0x1.8p2;

省略指数部分

十六进制浮点字面量必须包含 p 指数部分。

错误:

double x = 0x1.8;

正确:

double x = 0x1.8p0;

把指数理解为十进制指数

double x = 0x1p3;

它表示:

\[ 1 \times 2^3 \]

不是:

\[ 1 \times 10^3 \]

总结