第一次遇到浮点运算精度不够的问题
写了这么久程序,第一次受困于浮点运算精度不够的问题。比如下面的代码:
public static void DoubleTest()
{
double value1 = 100.85;
double value2 = 100.5;
double divisor = 0.025;
double difference = value1 - value2;
double mod = difference % divisor;
double quotient = difference / divisor;
Console.WriteLine( "=================DoubleTest=================" );
Console.WriteLine( "{0, -32} : {1}", "value1", value1 );
Console.WriteLine( "{0, -32} : {1}", "value2", value2 );
Console.WriteLine( "{0, -32} : {1}", "divisor", divisor );
Console.WriteLine( "{0, -32} : {1}", "difference = value1 - value2", difference );
Console.WriteLine( "{0, -32} : {1}", "mod = difference % divisor", mod );
Console.WriteLine( "{0, -32} : {1}", "quotient = differenct / divisor", quotient );
Console.WriteLine();
}
像 100.85-100.5=0.35 这么一目了然的操作,计算的结果却是0.349999999999994,导致我一个绘图的程序结果总是少一个点。查了些资料,IBM 网站上Brian Goetz 的这篇《您的小数点到哪里去了?》讲的比较清楚:计算机处理整型值很精确,但处理小数时用 float 或 double 浮点类型就会有误差了,而且这是不可避免的。
后来我采用的解决办法是把 double 类型的值放大 10000 倍,然后转成 long 长整型,中间计算过程全部用 long 型,最后把计算结果再转回 double 型并除以 10000 得到最终运算结果。之所以选择 10000 作为比例因子是因为我所有值的小数点后都不超过4位。这样就解决了利用 double 型产生的误差问题。之后我又用Decimal 类型作测试,把 double 转成 Decimal 再计算,结果也没有错误。MSDN 中讲“Decimal 值类型适用于要求使用大量有效的整数及小数位数并且没有舍入错误的财务计算”,看来把 double 转成 Decimal 是 .Net 中避免浮点运算误差比较正的路子。
记得刚开始学 C# 时,公司的师傅给的“C#编码规范”中有句话“不要比较浮点数的相等,如:10.0*0.1==1.0,不可靠”。当时还不理解,10.0*0.1=1.0天经地义,咋会不可靠呢?今天知道了,电脑还是不如人脑好使。
相关资料:
大坏蛋 数据类型的BUG还是???
Kathleen Dollard 正确运用数据类型




















后来我采用的解决办法是把 double 类型的值放大 10000 倍,然后转成 long 长整型,中间计算过程全部用 long 型,最后把计算结果再转回 double 型并除以 10000 得到最终运算结果。之所以选择 10000 作为比例因子是因为我所有值的小数点后都不超过4位。这样就解决了利用 double 型产生的误差问题。之后我又用Decimal 类型作测试,把 double 转成 Decimal 再计算,结果也没有错误。MSDN 中讲“Decimal 值类型适用于要求使用大量有效的整数及小数位数并且没有舍入错误的财务计算”,看来把 double 转成 Decimal 是 .Net 中避免浮点运算误差比较正的路子。
记得刚开始学 C# 时,公司的师傅给的“C#编码规范”中有句话“不要比较浮点数的相等,如:10.0*0.1==1.0,不可靠”。当时还不理解,10.0*0.1=1.0天经地义,咋会不可靠呢?今天知道了,电脑还是不如人脑好使。
相关资料:
大坏蛋 数据类型的BUG还是???
Kathleen Dollard 正确运用数据类型
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库