分类

链接

2011 年 12 月
 1234
567891011
12131415161718
19202122232425
262728293031  

近期文章

热门标签

新人福利,免费薅羊毛

现在位置:    首页 > .NET > 正文
共享办公室出租
c#中double四舍五入
.NET 暂无评论 阅读(3,731)

   计算机中的舍入问题,其实算是个老生长谈的问题。最初是在VB中产生过这种疑问,后来知道这是IEEE的一个标准,因此也成为各种语言通用的标准,说起来也是个“国际惯例”哩。这种舍入方法所采取的是四退六进五取偶,与国内传统的四舍五入还是有很大区别的,还有人专门写了一个四舍五入的程序,具体解释可参见百度百科等相关资讯,记得第一次接触这种舍入法应该是在大二的第一次物理实验课上,那位有点老学究模样的诸琢雄老师(可没有贬低的意思,过了五六年还能记得他的名字说明偶很尊敬他滴,据说他还是本校超级名捕之一呢)提到了这种舍入法,他称为“奇进偶不进”,又过了没多久,在测量学课上,黄晓时老师也讲到了,只不过称其为“单进双不进”,原理其实都是一样的。
    为什么想起提到这个问题呢,是因为在写平差程序时遇到一个问题,有点棘手,现在也没想出来为什么,各位可以试一下。
  double s = Math.Round((4.922F+4.921F)/2, 3);   //结果是4.921
  double s = Math.Round(4.9215F, 3);        //结果是4.922
  double s = Math.Round((4.922+4.921)/2, 3);    //结果是4.922
  double s = Math.Round(4.9215, 3);         //结果是4.922
    看出来了吗?就因为single和double的类型问题,所以舍入问题都会有些小bug,可是我的运算位数根本不需要double这么大的,难道每一次都要把single转换成double吗?好吧,就算我不厌其烦的转换,还是会出现问题,请看
  double d1 = Math.Round((Convert.ToDouble(4.922F) + Convert.ToDouble(4.921F)) / 2, 3);   //结果还是4.921
这回傻了吧?我也傻了,还好我的平差等级不高,进到哪一位问题都不大,否则就挂了。。。
    或许这是个低级的小问题,但我确实没有太好的对策,有一种解决方法是每次都加0.0001之类的,例如
  double s = Math.Round((4.922F + 4.921F) / 2 + 0.0001, 3);   //结果是4.922
这样看MS是对了,可以写个类似的函数,每次都加上这么一个数,但如果写个函数每个都加这个0.0001,那么则会出现下列情况
  double s = Math.Round((4.9214F + 4.9214F) / 2 + 0.0001, 3);  //结果是4.922
看来这种想法有点问题,继续修改,发现问题出在把那个1加在了重要的进位判断的位数上,那么如果把0.0001的小数点再左移一位呢:
  double s = Math.Round((4.922F + 4.921F) / 2 + 0.00001, 3);  //结果是4.922
  double s = Math.Round((4.9214F + 4.9214F) / 2 + 0.00001, 3); //结果是4.921
这回终于解决了,可以动手写个函数,既实现四舍五入,又可以解决single与double的这个小bug,当然,我想应该也可以把这个0.00001写作一个极小的常数,没有动手做过,只是猜想的
  internal double ChinaRound(double value, int decimals)
       
    return Math.Round(value + 1 / Math.Pow(10, decimals + 2), decimals, MidpointRounding.AwayFromZero);      
  }
    这里有个问题需要注意一下,就是负数的四舍五入问题,例如-1.5是该舍入到-1还是到-2呢?我这里采用的是-2,其实对于这种中间数舍入到哪一个问题都不大,关键是要做到统一,如果你想舍入到-1,恐怕还有另外写个分支结构,网上很多,有一个是
  if (value < 0)
  {
    return Math.Round(value + 5 / Math.Pow(10, decimals + 1), decimals, MidpointRounding.AwayFromZero);
  }
偶没测试过,有兴趣的人自己弄一下吧,如果哪位大侠有更好的解决方法,还望不吝赐教,多谢了

============ 欢迎各位老板打赏~ ===========

本文版权归Bruce's Blog所有,转载引用请完整注明以下信息:
本文作者:Bruce
本文地址:c#中double四舍五入 | Bruce's Blog

发表评论

留言无头像?