如何在C#中将一个数字四舍五入到两位小数?

491
我会使用 Math.Round 函数来完成这个操作。
16个回答

805

以下是一些示例:

decimal a = 1.994444M;

Math.Round(a, 2); //returns 1.99

decimal b = 1.995555M;

Math.Round(b, 2); //returns 2.00

你可能还想查看以下带有过载的银行家舍入/四舍五入:

Math.Round(a, 2, MidpointRounding.ToEven);

这里有更多关于它的信息,请点击这里


68
您应该澄清MidPointRounding.ToEven是默认设置。如果您想使用AwayFromZero,则需要使用重载。 - Brian Vander Plaats
7
如果您想将一个数值四舍五入保留两位小数,可以在进行四舍五入之前,将这个数值加上 0.005。同样地,如果您想向下舍入,则需在将数值传递给 Math.Round 函数之前减去 0.005 - orad
8
.NET默认使用"MidPointRounding.ToEven"(也称为"银行家舍入法")的原因是因为我们在学校里学习四舍五入时,遇到.5向上舍入会导致过度舍入。这在处理金钱、税务计算等方面会造成问题。 - asporter

124

试试这个:

twoDec = Math.Round(val, 2)

46

如果你需要一个字符串

> (1.7289).ToString("#.##")
"1.73"

或者是一个小数

> Math.Round((Decimal)x, 2)
1.73m
但是要记住!四舍五入不具有分配律,即 round(x*y) != round(x) * round(y)。因此,在计算的最后阶段再进行任何四舍五入,否则会丧失准确性。

36

个人而言,我从不对任何东西进行四舍五入。尽可能保持决断,因为在计算机科学中,四舍五入有点岔路。但是你确实需要为你的用户格式化数据,为此,我发现string.Format("{0:0.00}", number)是一个不错的方法。


这种方式在显示方面更好,特别是对于货币来说,因为使用 Math.round 的 £5.4 看起来不如 £5.40(这种方式)好看。 - Peter Gordon
我之前尝试过使用string.Format("0:0.00", number),但是它没有起作用。那些方括号非常重要,所以正确的写法是:string.Format("{0:0.00}", number)。 - FrenkyB
8
当你说“方括号”时,我希望你是指“花括号”。 - Mathemats
这也会四舍五入。1.009 => 1.01 - Donny V.

16

// 将数字转换为两位小数

String.Format("{0:0.00}", 140.6767554);        // "140.67"
String.Format("{0:0.00}", 140.1);             // "140.10"
String.Format("{0:0.00}", 140);              // "140.00"

Double d = 140.6767554;
Double dc = Math.Round((Double)d, 2);       //  140.67

decimal d = 140.6767554M;
decimal dc = Math.Round(d, 2);             //  140.67

=========

// just two decimal places
String.Format("{0:0.##}", 123.4567);      // "123.46"
String.Format("{0:0.##}", 123.4);         // "123.4"
String.Format("{0:0.##}", 123.0);         // "123"

也可以将“0”与“#”组合使用。

String.Format("{0:0.0#}", 123.4567)       // "123.46"
String.Format("{0:0.0#}", 123.4)          // "123.4"
String.Format("{0:0.0#}", 123.0)          // "123.0"

2
String.Format("{0:0.00}", 140.6767554); 不等于 "140.67"。实际上它会渲染成 "140.68" - 四舍五入。 - AndyT

16

维基百科有一个很好的页面介绍了一般的四舍五入。

所有.NET(托管)语言都可以使用公共语言运行时(CLR)的任何舍入机制。例如,Math.Round()(如上所述)方法允许开发人员指定舍入类型(舍入到偶数或远离零)。Convert.ToInt32()方法及其变体使用舍入到偶数Ceiling()Floor()方法是相关的。

您也可以使用自定义数字格式进行舍入。

请注意,Decimal.Round()使用的方法与Math.Round()不同;

这是一篇关于银行家舍入算法的有用的文章。 看看雷蒙德关于舍入的幽默文章...


你能详细说明一下“Decimal.Round()使用的方法与Math.Round()不同”吗?在您发布这篇文章14年后,似乎没有任何区别。 - Josh Gallagher

10
如果你想对一个数进行四舍五入,根据以下因素的不同使用方法,你可以得到不同的结果:使用Math.Round()函数的方式(是向上还是向下),你是否使用双精度或浮点数,以及是否采用中间舍入。尤其是当在函数内部使用运算或者需要对一个含有运算符的变量进行四舍五入时。比如说,你想要乘这两个数字:0.75 * 0.95 = 0.7125。没错吧?但在C#中不是这样。
让我们看看如果你想要将这个数字四舍五入到小数点后3位会发生什么:
double result = 0.75d * 0.95d; // result = 0.71249999999999991
double result = 0.75f * 0.95f; // result = 0.71249997615814209

result = Math.Round(result, 3, MidpointRounding.ToEven); // result = 0.712. Ok
result = Math.Round(result, 3, MidpointRounding.AwayFromZero); // result = 0.712. Should be 0.713

你看,如果你想将中点向下舍入,第一个Round()是正确的。但是如果你想将中点向上舍入,则第二个Round()是错误的。

这也适用于负数:

double result = -0.75 * 0.95;  //result = -0.71249999999999991
result = Math.Round(result, 3, MidpointRounding.ToEven); // result = -0.712. Ok
result = Math.Round(result, 3, MidpointRounding.AwayFromZero); // result = -0.712. Should be -0.713

所以,在我看来,你应该创建自己的包装函数来满足Math.Round()的要求。我创建了一个函数,其中参数'roundUp=true'表示四舍五入到下一个更大的数字。也就是说:0.7125四舍五入为0.713,-0.7125四舍五入为-0.712(因为-0.712 > -0.713)。这是我创建的函数,适用于任意数量的小数:

double Redondea(double value, int precision, bool roundUp = true)
{
    if ((decimal)value == 0.0m)
        return 0.0;

    double corrector = 1 / Math.Pow(10, precision + 2);

    if ((decimal)value < 0.0m)
    {
        if (roundUp)
            return Math.Round(value, precision, MidpointRounding.ToEven);
        else
            return Math.Round(value - corrector, precision, MidpointRounding.AwayFromZero);
    }
    else
    {
        if (roundUp)
            return Math.Round(value + corrector, precision, MidpointRounding.AwayFromZero);
        else
            return Math.Round(value, precision, MidpointRounding.ToEven);
    }
}

'corrector' 这个变量是用来修正操作浮点数或双精度数时的不准确性。


9

以下是用C#进行保留两位小数的方法:

label8.Text = valor_cuota .ToString("N2") ;

在VB.NET中:
 Imports System.Math
 round(label8.text,2)

7

我知道这是一个老问题,但请注意以下Math roundString format round之间的区别:

decimal d1 = (decimal)1.125;
Math.Round(d1, 2).Dump();   // returns 1.12
d1.ToString("#.##").Dump(); // returns "1.13"

decimal d2 = (decimal)1.1251;
Math.Round(d2, 2).Dump();   // returns 1.13
d2.ToString("#.##").Dump(); // returns "1.13"

7

我遇到了一个奇怪的情况,我有一个十进制变量,当序列化55.50时,它总是以数学上的默认值55.5设置。但是,我们的客户系统出于某种原因严重期望55.50,并且他们肯定期望是十进制。这就是我编写下面的帮助程序的原因,它始终将任何用零填充为2位数字的十进制值转换而不是发送字符串。

public static class DecimalExtensions
{
    public static decimal WithTwoDecimalPoints(this decimal val)
    {
        return decimal.Parse(val.ToString("0.00"));
    }
}

使用方法应该是

var sampleDecimalValueV1 = 2.5m;
Console.WriteLine(sampleDecimalValueV1.WithTwoDecimalPoints());

decimal sampleDecimalValueV1 = 2;
Console.WriteLine(sampleDecimalValueV1.WithTwoDecimalPoints());

输出:

2.50
2.00

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接