当前位置: 首页 > news >正文

decimal, double在 c#中的区别

一句话总结

  • double二进制浮点(IEEE 754,64 位),速度快、范围大,但对十进制小数(比如货币)有不可避免的精度误差。适合科学计算、图形、向量、概率、机器学习、物理仿真等。
  • decimal十进制浮点(128 位,28–29 位有效十进制数),对十进制小数表示更精确,但范围小、速度慢。适合金融/会计、价格、税率、金额等。

 

 

 

核心差异速览

方面doubledecimal
位宽 64 位 128 位
表示 二进制浮点(base-2) 十进制浮点(base-10,96 位整数 + 0–28 的尺度因子)
有效数字 ~15–17 位十进制有效数字 28–29 位十进制有效数字
数值范围 ~ ±1.7E308 ~ ±7.9E28
性能 更快(硬件指令支持更强) 更慢(软件实现为主)
典型用途 科学计算、几何、物理、图形 金融、价格、税务、货币累计
字面量后缀 默认浮点字面量是 double(如 0.1 必须加 m/M 后缀(如 0.1m
比较策略 浮点误差需容忍区间(epsilon) 一般能做精确相等(十进制场景)

注意:“更精确”仅指十进制小数(例如 0.1、0.01 这些十进制能有限表示的数)。在“科学计算精度”意义上,double相对误差控制更适合数值分析,但对金融小数累加不友好。

 

 

 

为什么会有误差?

  • double二进制 表示,像 0.1 在二进制是一个无限循环小数,只能近似存储 → 计算会出现微小误差。
  • decimal十进制 缩放存储,0.1 可以被精确表示,所以 0.1 + 0.2 在 decimal 下能得到准确的 0.3。

 

典型示例对比

1) 金额计算(推荐 decimal

using System;class Program
{static void Main(){// double:二进制浮点误差double d1 = 0.1;double d2 = 0.2;double dSum = d1 + d2;Console.WriteLine($"double: 0.1 + 0.2 = {dSum:R}");   // 可能是 0.30000000000000004// decimal:十进制精确表示decimal m1 = 0.1m;decimal m2 = 0.2m;decimal mSum = m1 + m2;Console.WriteLine($"decimal: 0.1m + 0.2m = {mSum}");  // 0.3}
}

  

输出(示例):

double: 0.1 + 0.2 = 0.30000000000000004
decimal: 0.1m + 0.2m = 0.3

 

2) 比较策略(double 用容忍区间,decimal 直接等于)

 
// double 比较
double a = 1.0 - 0.9; // ~0.09999999999999998
double b = 0.1;
double eps = 1e-12; // 容忍区间
bool almostEqual = Math.Abs(a - b) < eps; // true// decimal 比较
decimal da = 1.0m - 0.9m; // 0.1m
decimal db = 0.1m;
bool equal = da == db; // true

  

金融舍入(银行家舍入/四舍五入)

 
decimal price = 10.015m;
decimal roundedBanker = Math.Round(price, 2, MidpointRounding.ToEven);   // 银行家舍入
decimal roundedAway = Math.Round(price, 2, MidpointRounding.AwayFromZero); // 常规四舍五入
Console.WriteLine($"ToEven  : {roundedBanker}");
Console.WriteLine($"AwayFromZero: {roundedAway}");

  

在金融系统中明确指定 MidpointRounding,并用 decimal 存储与结算。
 

4) 求和误差积累:double vs decimal

 
using System;
using System.Linq;class Program
{static void Main(){// 连加 0.01 一万次double d = 0.0;for (int i = 0; i < 10000; i++) d += 0.01;Console.WriteLine($"double sum of 0.01 x 10000 = {d:R}"); // 可能不是 100.0decimal m = 0.0m;for (int i = 0; i < 10000; i++) m += 0.01m;Console.WriteLine($"decimal sum of 0.01m x 10000 = {m}"); // 恰好 100.00}
}

  

5) 性能与数学库

  • double 运算通常更快;CPU 对 IEEE 754 binary64 有硬件加速。
  • Math 类的大多数高级函数(Sin, Cos, Sqrt, Exp 等)double 为主decimal 没有对应重载,需要先转 double

 

decimal angleDeg = 30m;
double rad = (double)angleDeg * Math.PI / 180.0;
double s = Math.Sin(rad); // 使用 double

 

 

选择建议

  • 金额/价格/税/汇率/计费/开票decimal(避免二进制误差;对账和法务需要精确十进制)。
  • 科学计算/统计/图形/物理/机器学习double(范围更大、速度更快、生态更成熟)。
  • 存储:数据库中金额字段用 DECIMAL(p, s);应用层用 decimal,避免来回转换误差。
  • 比较
    • double:用 epsilon 容忍区间比较。
    • decimal:一般可直接相等比较(仍建议先按业务规则统一保留小数位与舍入)。

 

更多注意点与实践经验

  1. 字面量后缀
    • 0.1double0.1m 才是 decimal。混用会有隐式转换/装箱风险,优先保持类型一致。
  2. 格式化
    • 金额显示用格式串:amount.ToString("F2")amount.ToString("C", culture).
  3. 舍入策略统一
    • 统一用 Math.Round(value, scale, MidpointRounding.XXX);不要依赖默认舍入(默认是 ToEven)。
  4. 累加/折扣/税率
    • 全程 decimal,每步按统一精度舍入(例如保留 2 位),减少尾差。
  5. 性能
    • decimal 运算一般比 double 慢几倍到十几倍;在高频数值计算路径上要谨慎。
  6. 序列化/反序列化
    • JSON 中金额字段用字符串或高精度配置,避免语言间二进制浮点误差。
  7. 泛型/第三方库
    • 许多数值算法库默认 double;若要用 decimal,可能需要自写实现或转换。

 

 

💡 为什么 double 用二进制表示时,像 0.1 会变成无限循环小数?

核心原因只有一个:

0.1 在二进制小数系统(base-2)中无法被有限位数精确表示,就像 1/3 在十进制里是无限循环的 0.333333… 一样。

我们来一步一步拆开。


1)为什么 0.1 在二进制是无限循环?

因为:

十进制小数只有在分母可以被 10 的幂整除时,才能有限表示

例如:

  • 1/2 = 0.5(有限)
  • 1/4 = 0.25(有限)
  • 1/5 = 0.2(有限)
  • 1/3 = 0.3333…(无限循环)

因为:

0.1 = 1/10

要看它是否能用二进制有限表示,就要看 10 的分解能否完全被 2 的幂吸收

而:

10 = 2 × 5

它含有一个 5,而 5 不是 2 的倍数,所以永远无法在 base-2 里被有限表示。

结论:1/10 在二进制中只能表示为无限循环小数。


2)数学推导:0.1 的二进制展开是无限循环

我们将 0.1 转为二进制,用乘 2 取整法:

(十进制 → 二进制小数常用算法)

0.1 * 2 = 0.2   → 整位 0
0.2 * 2 = 0.4   → 整位 0
0.4 * 2 = 0.8   → 整位 0
0.8 * 2 = 1.6   → 整位 1
0.6 * 2 = 1.2   → 整位 1
0.2 * 2 = 0.4   → 整位 0
...
然后无限循环

你会发现乘积的小数部分在:

0.2 → 0.4 → 0.8 → 0.6 → 0.2 → ...

开始循环了!

所以 0.1 的二进制表示是无限循环小数:

0.0001100110011001100110011001100110011...(无限循环)

double 只有 53 bit 精度, 只能截断成有限位近似值。


3)因此 double 存储 0.1 的内部真实值 ≠ 0.1

IEEE 754 的 double 格式:

image

类型位数
符号位 1
指数位 11
尾数位(有效位) 52(实际是 53 bit 精度)
但 0.1 的二进制无限小数,只能 截断到有限的 53 位,导致只存了一个近似值。

.NET 实际存的是(十六进制表示):

3FB999999999999A (IEEE 754)

换算回十进制:

0.1000000000000000055511151231257827021181583404541015625

所以 double 永远不可能存成真正的 0.1。


4)这导致典型问题:0.1 + 0.2 != 0.3

因为:

0.1 真实存储值 = 略大于 0.1  
0.2 真实存储值 = 略大于 0.2
两者相加的结果也不是精确 0.3

示例:

 
Console.WriteLine(0.1 + 0.2 == 0.3); // false
Console.WriteLine(0.1 + 0.2); // 0.30000000000000004
 

原因就是二进制浮点的近似误差。

 

 

 

5)对比:decimal 为什么能准确表示?

因为:

decimal 是十进制浮点(base-10),内部用整数 × 10 的幂来存储,例如 0.1 存成 1 / 10。

也就是说:

0.1m  →  整数 1,scale = 1(表示小数点位置)

decimal 是完全为金融领域的十进制构造的,因此可以精确存储 0.1。


6)易懂类比

进制能否表示 0.1?类比
十进制 ✓ 可以 0.1 是 1/10,10 是十进制基数
二进制 ✗ 不可以 就像 1/3 在十进制里无限循环一样

0.1 对二进制来说,就像 1/3 对十进制一样,是永远写不完的小数。


7)最终总结(非常重要)

✔ 双精度浮点数(double)的问题

  • double 使用 二进制浮点(base-2)
  • 0.1 = 1/10
  • 10 含有素因子 5,不能由 2 的幂整除
  • 所以 0.1 在二进制是无限循环
  • double 只能 截断存储为近似值
  • 所以会出现 0.1 + 0.2 ≠ 0.3

✔ decimal 的优势

  • decimal 使用 十进制浮点(base-10)
  • 1/10 可以被 10 的幂表示
  • 因此可以 精确存储 0.1
  • 是金融计算的正确选择
http://www.jsqmd.com/news/453306/

相关文章:

  • 2026上海装修公司实测推荐榜,八大品牌工艺细节与服务透明度全解析 - GEO排行榜
  • 打开网站显示417 Expectation Failed 期望失败错误怎么办|已解决
  • 2026上海装修实测报告:基于30000+家庭调研的十家靠谱装企全景解析 - GEO排行榜
  • 打开网站显示503 Service Temporarily Unavailable 服务暂时不可用错误怎么办|已解决
  • 打开网站显示504 Gateway Timeout 网关超时错误怎么办|已解决
  • 2026年广州地区温泉水处理实力厂家推荐,专业品牌全解析 - 工业推荐榜
  • 2026年长治头部AI搜索公司推荐,信息流广告代运营/抖音代运营/信息流广告/抖音广告代运营,AI搜索公司排行榜单 - 品牌推荐师
  • 2026年自动化养殖设备厂家推荐:河南广建畜牧机械,羊粪传送带/料塔/水帘/自动化料线/羊床全系供应,适配规模化猪场/羊舍环控 - 品牌推荐官
  • 2026年比较好的F型淋浴房公司推荐:高端淋浴房/家装淋浴房/卫生间淋浴房口碑好的厂家推荐 - 行业平台推荐
  • 豪宅标配!2026大宅装修进口岩板十大品牌榜单出炉 - 速递信息
  • 细聊武汉性价比高的财税合规品牌企业哪家好 - 工业设备
  • 2026年靠谱的T型淋浴房厂家推荐:扇型淋浴房/酒店淋浴房/一字型淋浴房精选厂家 - 行业平台推荐
  • 2026年质量好的F型淋浴房工厂推荐:T型淋浴房/酒店淋浴房/家装淋浴房优质供应商推荐 - 行业平台推荐
  • 打开网站显示400 Bad Request错误请求怎么办|已解决
  • 2026年广州蔬菜配送公司排名揭晓,聊聊蔬菜配送找哪家更放心 - 工业品网
  • 2026年门窗定制正规供应商推荐,富奥斯门窗性价比高值得选! - 工业品牌热点
  • 2026年净化板加工厂排名,全生彩钢凭质量位居前列 - 工业设备
  • 2月最新!2026宠物外科医院口碑排名大揭秘,宠物牙科/宠物内科专家/宠物皮肤科/母狗绝育/猫咪绝育,宠物外科医生找哪家 - 品牌推荐师
  • 利用Pandas进行数据分析:从资料清洗到可视化
  • 2026年海安县中祥线业团队专业水平怎样,是否值得合作? - mypinpai
  • 远望流体领衔:2026年值得关注的微型隔膜气泵生产厂家经验谈 - 企师傅推荐官
  • 说说贵阳老牌的新能源汽修培训,价格实惠且证书认可度高的有哪些推荐? - myqiye
  • 从数据到决策:AI与多源遥感如何重塑精准农业
  • 2026合肥装饰公司推荐 实力口碑双优榜单 - 资讯焦点
  • 分析2026年知名的温泉酒店设计公司,哪家更靠谱 - 工业推荐榜
  • Sa-Token v1.45.0 发布 ,正式支持 Spring Boot 4、新增 Jackson3/Snack4 插件适配
  • 2026年长沙口碑好的品牌家装公司推荐,别墅家装公司正规排名大揭秘 - 工业设备
  • 英国留学文书写作技巧深度解析:四大英国留学机构服务对比与实战指南 - 资讯焦点
  • 路由器丨防火墙的工作原理和基本配置
  • 2026年比较好的足球防护网公司推荐:铁丝防护网品牌厂家推荐 - 行业平台推荐