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
相关推荐
一枚小小程序员哈7 分钟前
基于php的萌宠社区网站的设计与实现、基于php的宠物社区论坛的设计与实现
开发语言·php·宠物
老赵的博客1 小时前
QT的项目pro qmake编译
开发语言·qt
枯萎穿心攻击2 小时前
从 Unity UGUI 到 Unreal UMG 的交互与高效实践:UI 事件、坐标系适配与性能优化
开发语言·ui·unity·性能优化·ue5·游戏引擎·虚幻引擎
WALL-EC2 小时前
Qt工具栏中图标槽函数没有响应的问题分析
开发语言·qt·osgearth
熙客3 小时前
Java:HashMap的使用
java·开发语言
weixin_307779133 小时前
C++进程监视器与自动启动程序
开发语言·c++·算法
草莓熊Lotso4 小时前
【C语言强化训练16天】--从基础到进阶的蜕变之旅:Day12
c语言·开发语言·c++·刷题
不喜欢学数学er4 小时前
算法第五十三天:图论part04(第十一章)
开发语言·python·图论
你怎么知道我是队长4 小时前
python---构造函数、析构函数
开发语言·python
heeheeai4 小时前
jvm对象内存占用
开发语言·jvm·内存分析