float.h 核心目的
定義浮點類型 (float、double、long double) 的實現相關特性:精度、範圍、極值。所有宏為 #define 常量表達式,編譯期可用。
命名規律
FLT_:float (單精度,通常 IEEE 754 binary32)
DBL_:double (雙精度,通常 IEEE 754 binary64)
LDBL_:long double (擴展精度,x86 80 位、ARM64 128 位、MSVC 同 double)
完整宏分類表 (IEEE 754 典型值)
1. 精度相關
| 宏 | 含義 | float 典型值 | double 典型值 |
| FLT_RADIX | 指數基數 (底數) | 2 (二進制) |
| FLT_MANT_DIG | 尾數位數 (含隱含位,基數為 FLT_RADIX) | 24 | 53 |
| FLT_DIG | 十進制精度位數 (保證往返不變) | 6 | 15 |
| FLT_DECIMAL_DIG | 十進制位數 (任意精度轉換不變, C99) | 9 | 17 |
2. 指數範圍
| 宏 | 含義 | float | double |
| FLT_MIN_EXP | 最小指數 (基數 FLT_RADIX) | -125 | -1021 |
| FLT_MAX_EXP | 最大指數 | 128 | 1024 |
| FLT_MIN_10_EXP | 最小十進制指數 (10^exp 為正常化數) | -37 | -307 |
| FLT_MAX_10_EXP | 最大十進制指數 | 38 | 308 |
3. 數值極值
| 宏 | 含義 | float 典型值 | double 典型值 |
| FLT_MAX | 最大有限值 | 3.402823466e+38F | 1.7976931348623157e+308 |
| FLT_MIN | 最小正正常化數 | 1.175494351e-38F | 2.2250738585072014e-308 |
| FLT_TRUE_MIN | 最小正非正常化數 (C99) | 1.401298464e-45F | 4.9406564584124654e-324 |
| FLT_EPSILON | 機器極小值 (1.0 + eps != 1.0 的最小值) | 1.192092896e-07F | 2.2204460492503131e-16 |
4. 特殊值支持 (C99)
| 宏 | 含義 |
| FLT_HAS_SUBNORM | 支持非正常化數 (0/1/2: 不支持/支持/不定) |
| FLT_HAS_INFINITY | 支持無窮大 |
| FLT_HAS_QUIET_NAN | 支持安靜 NaN |
| FLT_HAS_SIGNALING_NAN | 支持信號 NaN |
浮點數表示模型
值 = (-1)^符號 × 尾數 × 基數^指數
IEEE 754 binary32 (float): 1 位符號 | 8 位指數 (偏移 127) | 23 位尾數 (隱含 1) = 32 位
IEEE 754 binary64 (double): 1 位符號 | 11 位指數 (偏移 1023) | 52 位尾數 (隱含 1) = 64 位
實戰:運行時檢測浮點特性
#include <float.h>
#include <stdio.h>
void print_float_props(const char *name,
int mant_dig, int dig, int max_10_exp, int min_10_exp,
double max, double min, double eps) {
printf("%s:\n", name);
printf(" 尾數位數: %d, 十進制精度: %d\n", mant_dig, dig);
printf(" 指數範圍: 10^%d ~ 10^%d\n", min_10_exp, max_10_exp);
printf(" 數值範圍: %e ~ %e\n", min, max);
printf(" 機器極小值: %e\n\n", eps);
}
int main() {
print_float_props("float",
FLT_MANT_DIG, FLT_DIG, FLT_MAX_10_EXP, FLT_MIN_10_EXP,
FLT_MAX, FLT_MIN, FLT_EPSILON);
print_float_props("double",
DBL_MANT_DIG, DBL_DIG, DBL_MAX_10_EXP, DBL_MIN_10_EXP,
DBL_MAX, DBL_MIN, DBL_EPSILON);
print_float_props("long double",
LDBL_MANT_DIG, LDBL_DIG, LDBL_MAX_10_EXP, LDBL_MIN_10_EXP,
LDBL_MAX, LDBL_MIN, LDBL_EPSILON);
return 0;
}
關鍵應用場景
1. 浮點數比較容差
int float_eq(float a, float b) {
return fabs(a - b) <= FLT_EPSILON * fmax(fabs(a), fabs(b));
}
// 或使用相對誤差
#define FLOAT_EQ(a,b) (fabs((a)-(b)) <= 1e-6 * fmax(fabs(a), fabs(b)))
2. 序列化精度控制
// 保證 float 往返不失真需 9 位有效數字
printf("%.9g", f); // 或 %.8e
// double 需 17 位
printf("%.17g", d);
3. 防止溢出/下溢檢查
if (val > FLT_MAX / 2) { /* 乘法可能溢出 */ }
if (val < FLT_MIN * 2 && val != 0) { /* 除法可能下溢 */ }
4. 編譯期靜態斷言
#include <assert.h>
_Static_assert(FLT_DIG >= 6, "float 精度不足");
_Static_assert(DBL_DIG >= 15, "double 精度不足");
_Static_assert(FLT_RADIX == 2, "非二進制浮點,需特殊處理");
跨平台差異提示
| 平台/編譯器 | long double | FLT_EVAL_METHOD |
| x86 GCC/Clang | 80 位擴展精度 (64 位尾數) | 2 (表達式按 long double 計算) |
| x86_64 GCC/Clang | 80 位 (存儲 16 位元組對齊) | 0 (按類型計算) |
| ARM64 GCC/Clang | 128 位 IEEE quadruple | 0 |
| MSVC (所有架構) | 同 double (64 位) | 0 |
FLT_EVAL_METHOD 影響中間計算精度:0 按類型、1 float 提升 double、2 全部提升 long double。