004 C++的浮点类型(Floating-Point Types)
作者Lou Xiao, deepseek创建时间2025-04-02 06:55:53更新时间2025-04-02 06:55:53
1 浮点类型概述
1.1 基本概念
- 浮点类型用于表示实数(带小数点的数)
- 在C++中有三种基本浮点类型:
float
,double
,long double
- 遵循IEEE 754标准(大多数现代系统)
1.2 浮点类型特性
类型 | 字节大小(典型) | 精度(十进制位数) | 范围(典型) | 后缀 |
---|---|---|---|---|
float | 4字节 | 6-9位 | ±1.18×10⁻³⁸ to ±3.4×10³⁸ | f或F |
double | 8字节 | 15-17位 | ±2.23×10⁻³⁰⁸ to ±1.8×10³⁰⁸ | 无或l/L |
long double | 8-16字节 | 18-36位 | 范围更大 | L |
1.3 浮点字面量
类型 | 后缀 | 示例 | 说明 |
---|---|---|---|
float | f/F | 3.14f, 1.0e-5F | 单精度浮点数 |
double | 无 | 3.14, 1.0e-5 | 双精度浮点数 |
long double | l/L | 3.14L, 1.0e-5L | 扩展精度浮点数 |
浮点表示形式
- 十进制小数:3.14159
- 科学计数法:6.022e23
(6.022×10²³)
- 十六进制浮点(C++17):0x1.2p3
(1.125×2³=9.0)
1.4 浮点特性(<limits>
)
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
#include <limits>
2
#include <iostream>
3
4
int main() {
5
std::cout << "float范围: "
6
<< std::numeric_limits<float>::min() << " 到 "
7
<< std::numeric_limits<float>::max() << '\n';
8
9
std::cout << "float精度位数: "
10
<< std::numeric_limits<float>::digits10 << '\n';
11
12
std::cout << "float epsilon: "
13
<< std::numeric_limits<float>::epsilon() << '\n';
14
15
return 0;
16
}
2 浮点类型声明与初始化
2.1 声明方式
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
float f; // 声明一个float变量
2
double d; // 声明一个double变量
3
long double ld; // 声明一个long double变量
2.2 初始化方式
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
float f1 = 3.14f; // 使用f后缀表示float
2
double d1 = 3.14; // 默认是double
3
long double ld1 = 3.14L;// 使用L后缀表示long double
4
5
// 科学计数法表示
6
double d2 = 1.23e5; // 1.23 × 10^5
7
float f2 = 1.23e-5f; // 1.23 × 10^-5
三、浮点类型特性详解
3.1 精度问题
- 浮点数在内存中以二进制形式存储,不能精确表示所有十进制小数
- 示例:
cpp double d = 0.1 + 0.2; // 结果可能不是精确的0.3
- 比较浮点数应使用容差比较而非直接相等比较
3.2 浮点特殊值
值/宏 | 描述 | 示例 |
---|---|---|
INFINITY | 正无穷大 | 1.0/0.0 |
NAN | 非数字(Not a Number) | 0.0/0.0 |
HUGE_VAL | 表示无穷大的double值 | HUGE_VAL |
FLT_MAX | float最大值 | std::numeric_limits<float>::max() |
FLT_MIN | float最小正值 | std::numeric_limits<float>::min() |
3.3 浮点环境
<cfenv>
头文件提供浮点环境控制- 常见浮点异常:
- FE_DIVBYZERO
- FE_INEXACT
- FE_INVALID
- FE_OVERFLOW
- FE_UNDERFLOW
四、浮点运算与类型转换
4.1 算术运算
- 支持基本算术运算:
+
,-
,*
,/
- 数学函数在
<cmath>
中定义:
cpp #include <cmath> double result = std::sqrt(2.0);
4.2 类型转换
4.2.1 隐式转换
- 遵循从小到大的转换规则:
float
→double
→long double
- 整数可以隐式转换为浮点数
4.2.2 显式转换
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
double d = 3.14;
2
float f = static_cast<float>(d); // C++风格转换
3
float f2 = (float)d; // C风格转换
4.3 浮点与整型的比较
- 比较时整型会转换为浮点型
- 注意精度丢失问题
五、浮点类型的实际应用
5.1 何时使用哪种类型
float
:内存受限场景,不需要高精度double
:默认选择,适合大多数应用long double
:需要极高精度的科学计算
5.2 性能考虑
- 现代CPU通常对
double
有优化,性能与float
相差不大 - SIMD指令可以并行处理多个
float
运算
5.3 避免常见陷阱
避免相等比较:
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
// 错误方式
2
if (a == b) { ... }
3
4
// 正确方式
5
const double epsilon = 1e-10;
6
if (std::abs(a - b) < epsilon) { ... }
避免大数吃小数:
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
double big = 1e20;
2
double small = 1.0;
3
// big + small == big,因为small被忽略了
注意累积误差:
- 多次运算可能导致误差累积
- 对于金融计算,考虑使用定点数库
六、C++标准库支持
6.1 <limits>
头文件
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
#include <limits>
2
std::numeric_limits<double>::max(); // 最大值
3
std::numeric_limits<float>::min(); // 最小正值
4
std::numeric_limits<long double>::digits10; // 十进制精度位数
6.2 <cmath>
数学函数
函数 | 描述 |
---|---|
std::sqrt(x) | 平方根 |
std::pow(x,y) | x的y次方 |
std::exp(x) | e的x次方 |
std::log(x) | 自然对数 |
std::log10(x) | 以10为底的对数 |
std::sin(x) | 正弦 |
std::cos(x) | 余弦 |
std::tan(x) | 正切 |
std::ceil(x) | 向上取整 |
std::floor(x) | 向下取整 |
std::round(x) | 四舍五入 |
std::fmod(x,y) | 浮点余数 |
std::isnan(x) | 检查是否为NaN |
std::isinf(x) | 检查是否为无穷大 |
6.3 <iomanip>
格式化输出
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
#include <iostream>
2
#include <iomanip>
3
4
double d = 1.23456789;
5
std::cout << std::setprecision(5) << d; // 输出1.2346
七、C++11/14/17/20新增特性
7.1 十六进制浮点字面量(C++17)
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
double d = 0x1.2p3; // 1.2(十六进制) × 2^3 = 9.0
7.2 数学特殊函数(C++17)
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
#include <cmath>
2
std::assoc_laguerre(2, 1, 0.5); // 关联拉盖尔多项式
7.3 浮点原子操作(C++20)
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
#include <atomic>
2
std::atomic<double> atomic_double(3.14);
8 最佳实践总结
- 默认使用
double
,除非有明确理由使用float
或long double
- 避免直接比较浮点数相等,使用容差比较
- 注意运算顺序对精度的影响
- 了解平台特定的浮点实现差异
- 对于关键计算,考虑使用高精度数学库如GMP、MPFR
- 使用
static_cast
进行显式浮点转换 - 注意浮点数的序列化和反序列化可能引入精度问题
- 避免直接比较浮点数是否相等
- 注意浮点运算的累积误差
- 科学计算考虑使用
long double
- 处理货币等精确计算考虑使用定点数或专用库
- 注意浮点运算的优化可能改变结果(如
-ffast-math
) - 使用
std::numeric_limits
获取类型特性
9. 示例代码
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
#include <iostream>
2
#include <cmath>
3
#include <limits>
4
#include <cfenv>
5
6
int main() {
7
// 基本浮点类型
8
float f = 3.14159f;
9
double d = 2.718281828459045;
10
long double ld = 1.6180339887498948482L;
11
12
// 浮点运算
13
double sum = 0.1 + 0.2;
14
std::cout << "0.1 + 0.2 = " << sum << " (可能不等于0.3)\n";
15
16
// 浮点比较
17
if (std::fabs(sum - 0.3) < 1e-10) {
18
std::cout << "0.1 + 0.2 ≈ 0.3\n";
19
}
20
21
// 特殊值
22
double inf = 1.0 / 0.0;
23
double nan = 0.0 / 0.0;
24
std::cout << "inf: " << inf << ", isnan: " << std::isnan(nan) << '\n';
25
26
// 数学函数
27
std::cout << "sqrt(2) = " << std::sqrt(2.0) << '\n';
28
std::cout << "sin(π/2) = " << std::sin(3.14159265358979323846/2) << '\n';
29
30
return 0;
31
}
文章目录