当前位置:编程学习 > C#/ASP.NET >>

Math.Round()函数的问题

这个
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()函数,我靠,看了函数解释,乖乖,这不正符合人家的要求嘛。于是拿来测试了下,谁知道不像我想的那样。

不知道哪位能解释下这个函数的原理,以及为什么会出现上面的那种情况,谢谢。 --------------------编程问答-------------------- Math.Round()函数 
加上MidpointRounding.AwayFromZero可以不分奇偶四舍五入,如果不加此屬性就正如LZ說的這種情況 --------------------编程问答--------------------
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;
}


 

 
--------------------编程问答-------------------- 以上就是原理 --------------------编程问答-------------------- Round函数的mode参数其实已经很好地说明这个问题,AwayFromZero模式是四舍五入模式,ToEven模式是四舍六入模式,你提供的程序测试结果符合四舍六入的规则。 --------------------编程问答-------------------- 学习了 --------------------编程问答-------------------- Round函数的mode参数其实已经很好地说明这个问题,AwayFromZero模式是四舍五入模式,ToEven模式是四舍六入模式,你提供的程序测试结果符合四舍六入的规则。
============
有道理
学习ing --------------------编程问答-------------------- 我用的是2003(没有办法,公司做系统还是用的2003,囧),没有第三参数的,看了下原来第三参数的是2005加入的。
没有看2005,只是照样在2005里面测试了下,汗。
我是从C++转向C#的,C#还非常之不熟悉。多谢各位的帮助。 --------------------编程问答-------------------- 看下面的代碼,會是你想要的結果

    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類型,因此會準確一些。 --------------------编程问答-------------------- 另外,樓上各位所述“Math.Round()函数,加上MidpointRounding.AwayFromZero”是沒有用的,這個參數加上去就相當於VS2003的Round. --------------------编程问答-------------------- 更正,Math.Round()函数,加上MidpointRounding.ToEven ,就相當於VS2003的Round. --------------------编程问答-------------------- 学了 --------------------编程问答-------------------- 參數設置為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());

--------------------编程问答-------------------- 加上M后缀
这样编译器才认
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,