C# 浮点数与定点数详细解析

C# 浮点数与定点数详细解析

在 C# 中,数值类型主要分为:

  • 整数型int, long 等)
  • 浮点型float, double
  • 定点型decimal

浮点数和定点数在内部的表示方式不同,导致它们的 精度、范围、性能、使用场景 都有明显区别。本文将详细剖析两者的原理与对比。


1️⃣ 浮点数(float / double)

1.1 表示方法(IEEE 754)

浮点数采用 二进制科学计数法 存储:

复制代码
值 = (-1)^符号位 × 1.尾数 × 2^(指数 - 偏移量)
  • 符号位:1 位,表示正负
  • 指数位:控制缩放大小
  • 尾数位:存储有效数字
类型 位数 符号位 指数位 尾数位
float 32 1 8 23
double 64 1 11 52

👉 范围极大,但精度有限。某些小数在二进制中无法精确表示。


1.2 小数的二进制表示

浮点数小数用 2 的负次方来组合:

复制代码
0.101₂ = 2⁻¹ + 2⁻³ = 0.5 + 0.125 = 0.625

但像 0.1 这样的十进制分数,在二进制中是无限循环小数:

复制代码
0.1₁₀ = 0.0001100110011...₂

只能近似存储 → 运算会出现误差。


1.3 常见误差示例

csharp 复制代码
Console.WriteLine(0.1 + 0.2 == 0.3);  // False
Console.WriteLine(0.1 + 0.2);         // 0.30000000000000004

原因:二进制截断 → 加法结果不是精确的 0.3。


1.4 特殊值

浮点数里其实还藏着几个特别的数,它们在实际开发里经常会遇到:

  • 正无穷 / 负无穷

    当结果太大,已经超过浮点数能表示的范围时,就会变成无穷大:

    • double.PositiveInfinity → 正无穷
    • double.NegativeInfinity → 负无穷
  • NaN(Not a Number,意思是"不是一个数")

    一些数学上不合法的运算会得到 NaN,比如:

    • 0.0 / 0.0
    • Math.Sqrt(-1)
      特别注意:NaN 和任何值比较(甚至跟自己比)都会是 false
    csharp 复制代码
    Console.WriteLine(double.NaN == double.NaN); // false
  • +0 和 -0

    浮点数里其实区分正零和负零,不过在大多数运算里,它们没区别:

    • +0 == -0 结果是 true

    • 但在某些场景(比如除法)下会有区别:

      csharp 复制代码
      Console.WriteLine(1.0 / +0); // Infinity
      Console.WriteLine(1.0 / -0); // -Infinity

1.5 浮点数比较正确姿势

  1. 近似比较(epsilon 容差)
csharp 复制代码
bool IsEqual(double a, double b, double eps = 1e-10)
    => Math.Abs(a - b) < eps;
  1. 游戏开发常见做法(Godot / Unity)
csharp 复制代码
Mathf.Approximately(a, b);      // Unity
Mathf.IsEqualApprox(a, b);      // Godot
  1. 避免直接用 ==
    除非数据本身是整数运算得来的,或者特别确定是完全相等。

2️⃣ 定点数(decimal)

2.1 表示方法

  • 总共 128 位存储

    • 96 位存有效数字
    • 16 位存小数位精度(scale,小数点位置)
  • 十进制方式存储 → 可以精确表示 0.10.20.3


2.2 特点

  • 高精度(28-29 位有效数字)
  • 范围比 double 小,但能避免浮点误差
  • 计算速度比浮点数慢(大约 5~20 倍),因为是软件实现而不是硬件指令

2.3 示例

csharp 复制代码
decimal a = 0.1m + 0.2m;
decimal b = 0.3m;
Console.WriteLine(a == b); // True

👉 在货币、金融计算中,应优先使用 decimal


3️⃣ 性能对比

特性 float/double(浮点数) decimal(定点数)
存储方式 二进制科学计数法 十进制定点数
精度 有误差(约 15~16 位) 高精度(28~29 位)
范围 极大 较小
运算速度 硬件支持,速度极快 慢(软件实现)
适用场景 科学计算、物理模拟 金融、货币

4️⃣ 小结

  • 浮点数 → 范围大、速度快,但存在精度误差
  • decimal → 精度高,适合金融,但性能较差
  • 判断浮点数相等时,应使用 近似比较 而不是 ==
  • 在游戏或物理模拟 → 用 float/double
  • 在账务、价格计算 → 用 decimal
相关推荐
沐知全栈开发4 小时前
SVG 参考手册
开发语言
Summer_Uncle4 小时前
【C++学习】对象特性--继承
开发语言·c++·学习
西贝爱学习4 小时前
【QT】安装包
开发语言·qt
徐凤年lll5 小时前
python 初学2
开发语言·python
2301_801252225 小时前
Mybatis的添加和修改功能
java·开发语言·mybatis
行思理5 小时前
IntelliJIdea 创建java spring boot程序
java·开发语言·spring boot
散峰而望6 小时前
C语言刷题(一)
c语言·开发语言·编辑器·github·visual studio
CN-Dust6 小时前
【C++】2025CSP-J第二轮真题及解析
开发语言·c++·算法
温柔一只鬼.6 小时前
Java数组
java·开发语言·算法
仟濹7 小时前
「经典图形题」集合 | C/C++
c语言·开发语言·c++