Math.Round()函数的问题

gamecomic 2008-01-11 03:13:59
这个
1 Math.Round(4.35, 1);
2 Math.Round(4.45, 1);
3 Math.Round(4.49, 1);
4 Math.Round(4.43, 1);
上面4个的答案相信大家很容易回答出来吧。
四舍六入五成双,这个以前论坛又人总结过了。

但是下面几个数值,大家能一眼看出来么?

Math.Round(4.00095, 4) ;
Math.Round(4.00195, 4);
Math.Round(7.00095, 4);
Math.Round(7.00195, 4);
Math.Round(5.00095, 4);
Math.Round(5.00195, 4);
Math.Round(5.0095, 3);
看出答案后然后测试下吧,看看有谁的答案是全对的。
开始还一位是2003的bug,用2005测试也一样。

其实事情是这样的,客户有个要求是传给我一个double,然后是精度值n,让我保留n位小数,条件是如果小数部分的第n+1位为1~4,则舍去,如果第n+1位为6~9,则进,如果第n+1位为5,则看第n位的值,如果是偶数,则舍,是奇数则进位。
于是我写了一个,后来测试的时候发现有些问题,在上网查资料的时候查到了Math.Round()函数,我靠,看了函数解释,乖乖,这不正符合人家的要求嘛。于是拿来测试了下,谁知道不像我想的那样。

不知道哪位能解释下这个函数的原理,以及为什么会出现上面的那种情况,谢谢。
...全文
9526 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
草原可可 2008-01-11
  • 打赏
  • 举报
回复
加上M后缀
这样编译器才认
nj_1st_excellence 2008-01-11
  • 打赏
  • 举报
回复
參數設置為AwayFromZero的時候會出現以下例外的情況:5被舍去,而不會進一位.
Response.Write("<br/>" + Math.Round(5.00095, 4, MidpointRounding.AwayFromZero).ToString());
只有取精度是4的時候會這樣.
所以最好將數字轉換為decimal類型.

下面這種情況就不會咯!
Response.Write("<br/>" + Math.Round(5.00095m, 4, MidpointRounding.AwayFromZero).ToString());

changjiangzhibin 2008-01-11
  • 打赏
  • 举报
回复
学了
boblaw 2008-01-11
  • 打赏
  • 举报
回复
更正,Math.Round()函数,加上MidpointRounding.ToEven ,就相當於VS2003的Round.
boblaw 2008-01-11
  • 打赏
  • 举报
回复
另外,樓上各位所述“Math.Round()函数,加上MidpointRounding.AwayFromZero”是沒有用的,這個參數加上去就相當於VS2003的Round.
boblaw 2008-01-11
  • 打赏
  • 举报
回复
看下面的代碼,會是你想要的結果

class Program
{
static void Main(string[] args)
{
Console.WriteLine("Math.Round(4.00095, 4):{0}", Math.Round(4.00095M, 4));
Console.WriteLine("Math.Round(4.00195, 4):{0}", Math.Round(4.00195M, 4));
Console.WriteLine("Math.Round(7.00095, 4):{0}", Math.Round(7.00095M, 4));
Console.WriteLine("Math.Round(7.00195, 4):{0}", Math.Round(7.00195M, 4));
Console.WriteLine("Math.Round(5.00095, 4):{0}", Math.Round(5.00095M, 4));
Console.WriteLine("Math.Round(5.00195, 4):{0}", Math.Round(5.00195M, 4));
Console.WriteLine("Math.Round(5.0095, 3):{0}", Math.Round(5.0095M, 3));

Console.WriteLine("Math.Round(5.0295, 3):{0}", Math.Round(5.0295M, 3));
Console.WriteLine("Math.Round(5.0395, 3):{0}", Math.Round(5.0395M, 3));

Console.WriteLine("按任意鍵退出...");
Console.ReadKey();
}
}


之所以和你的結果不一樣,是因為你的代碼中直接用4.00095來表示,這樣C#會認為是浮點數double類型,而浮點數的表示往往會不準確,但是如果加個M後綴,則表示為Decimal類型,因此會準確一些。
gamecomic 2008-01-11
  • 打赏
  • 举报
回复
我用的是2003(没有办法,公司做系统还是用的2003,囧),没有第三参数的,看了下原来第三参数的是2005加入的。
没有看2005,只是照样在2005里面测试了下,汗。
我是从C++转向C#的,C#还非常之不熟悉。多谢各位的帮助。
xiaojing7 2008-01-11
  • 打赏
  • 举报
回复
Round函数的mode参数其实已经很好地说明这个问题,AwayFromZero模式是四舍五入模式,ToEven模式是四舍六入模式,你提供的程序测试结果符合四舍六入的规则。
============
有道理
学习ing
jetxia 2008-01-11
  • 打赏
  • 举报
回复
学习了
lijipan 2008-01-11
  • 打赏
  • 举报
回复
Round函数的mode参数其实已经很好地说明这个问题,AwayFromZero模式是四舍五入模式,ToEven模式是四舍六入模式,你提供的程序测试结果符合四舍六入的规则。
jinjazz 2008-01-11
  • 打赏
  • 举报
回复
以上就是原理
jinjazz 2008-01-11
  • 打赏
  • 举报
回复
private static unsafe double InternalRound(double value, int digits, MidpointRounding mode)
{
if (Abs(value) < doubleRoundLimit)
{
double num = roundPower10Double[digits];
value *= num;
if (mode == MidpointRounding.AwayFromZero)
{
double num2 = SplitFractionDouble(&value);
if (Abs(num2) >= 0.5)
{
value += Sign(num2);
}
}
else
{
value = Round(value);
}
value /= num;
}
return value;
}





TNT_1st_excellence 2008-01-11
  • 打赏
  • 举报
回复
Math.Round()函数
加上MidpointRounding.AwayFromZero可以不分奇偶四舍五入,如果不加此屬性就正如LZ說的這種情況

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧