将双精度数格式化为两位小数

54

我一直在尝试使该答案打印出两位小数。所有涉及的数学运算都必须保持这个两位小数的格式。我尝试过一些方法,但不确定要更改什么才能使它起作用。

double pdt1 = 239.99;
double pdt1Total;
double pdt2 = 129.75;
double pdt2Total;
double pdt3 = 99.95;
double pdt3Total;
double pdt4 = 350.89;
double pdt4Total;
double wage = 200;
double percentage = 9;
double total;
double answer;
double i = 100;
double a;
double b;
double c;
double d;


Console.Write("Enter number sold of product #1: ");
a = Convert.ToInt32(Console.ReadLine());

Console.Write("Enter number sold of product #2: ");
b = Convert.ToInt32(Console.ReadLine());

Console.Write("Enter number sold of product #3: ");
c = Convert.ToInt32(Console.ReadLine());

Console.Write("Enter number sold of product #4: ");
d = Convert.ToInt32(Console.ReadLine());



pdt1Total = a * pdt1;
pdt2Total = b * pdt2;
pdt3Total = c * pdt3;
pdt4Total = d * pdt4;

total = (pdt1Total + pdt2Total + pdt3Total + pdt4Total);



string.Format("{0:0.00}", total);
string.Format("{0:0.00}", answer = (total * percentage / i) + wage);


Console.WriteLine("Earnings this week: "+answer+"");

2
你可能不想在货币计算中使用浮点数——舍入误差最终会让你吃亏。虽然似乎没有内置的解决方案,但可以参考类似于http://www.codeproject.com/Articles/28244/A-Money-type-for-the-CLR的链接来获得灵感。话虽如此,当你开始进行百分比计算等操作时,你就不能避免再增加几个小数位了... - canton7
我需要保留小数点后两位,但答案不会反映出来。因此,格式应为:209.00(如果您选择产品三的一个产品并将其他所有产品都设置为零,则应该是答案)。 - Dan Cairnes
你得到了什么答案? - Stobor
我之前得到的是108.9955,但现在使用Damith的代码就可以了。 - Dan Cairnes
1
可能是重复的问题,参见使用字符串格式显示小数点后两位或简单整数 - Sruit A.Suk
8个回答

88

根据你的需求,你可以选择以下任何一种。每种方法后面都标有输出结果。

你可以选择你需要的那个

这将四舍五入

decimal d = 2.5789m;
Console.WriteLine(d.ToString("#.##")); // 2.58

这将确保写入2位小数。

d = 2.5m;
Console.WriteLine(d.ToString("F")); //2.50

如果你想要写逗号,你可以使用这个

d=23545789.5432m;
Console.WriteLine(d.ToString("n2")); //23,545,789.54

如果您想返回小数值的四舍五入值,可以这样做:

d = 2.578m;
d = decimal.Round(d, 2, MidpointRounding.AwayFromZero); //2.58

2
因为这个例子使用了十进制,而问题是关于双精度的,所以被踩了。 - Richard McKenna

86

string.Format 不会改变原始值,但会返回一个格式化后的字符串。例如:

string.Format不会更改原始值,而是将其格式化为字符串并返回。

Console.WriteLine("Earnings this week: {0:0.00}", answer);
注意:Console.WriteLine允许行内字符串格式化。上述代码等价于:
Console.WriteLine("Earnings this week: " + string.Format("{0:0.00}", answer));

这不会截断末尾的额外0。请使用#.##:https://dev59.com/BWMl5IYBdhLWcg3wa2fW#18418762 - Tamás Sengel

15

您可以像这样将 double 四舍五入到小数点后两位:

double c;
c = Math.Round(c, 2);

但请注意四舍五入最终会给你带来麻烦,因此请谨慎使用。

相反,请使用decimal数据类型。


2
我尝试使用Math.Round,结果很快就变得不准确了。 - Dan Cairnes
1
为什么在四舍五入时双精度和十进制之间有区别? - Emil

13

我建议使用固定点("F")格式说明符(正如Ehsan所提到的)。请参阅标准数值格式字符串

使用此选项,您甚至可以拥有可配置的小数位数:

public string ValueAsString(double value, int decimalPlaces)
{
    return value.ToString($"F{decimalPlaces}");
}

10
    double d =  3.1493745;
    string s = $"{d:0.00}"; // or $"{d:#.##}"
    Console.WriteLine(s); // Displays 3.15

3

既然您在处理货币方面,为什么不直接这样做:

Console.Writeline("Earnings this week: {0:c}", answer);

这将把答案格式化为货币,因此在我的机器上(英国),它会显示为:

本周收入:£209.00


1
问题在于,当您对所有具有两位小数的数字进行加法和乘法运算时,您期望不会出现舍入误差,但请记住,双精度浮点数的内部表示是基于二进制而不是十进制!因此,像0.1这样的十进制数在二进制中可能是0.101010101010110011...,其中包含无限多个小数位(存储在双精度浮点数中的值将是一个数字N,其中:)。
 0.1-Math.Pow(2,-64) < N < 0.1+Math.Pow(2,-64) 

因此,像12.3+0.1这样的操作可能不是与12.4完全相同的64位双精度值(或者12.456*10可能与124.56不同),因为存在舍入误差。例如,如果您将12.3+0.1的结果存储在数据库中,作为double precision数字类型的表/列字段的结果,然后选择WHERE xx=12.4,您可能会发现您存储了一个不完全等于12.4的数字,SQL查询将不会返回记录;因此,如果您不能使用十进制数据类型(其内部表示为基数10)并且必须使用“double”数据类型,则必须在每次加法或乘法之后进行一些规范化处理:
double freqMHz= freqkHz.MulRound(0.001); // freqkHz*0.001
double amountEuro= amountEuro.AddRound(delta); // amountEuro+delta


    public static double AddRound(this double d,double val)
    {
        return double.Parse(string.Format("{0:g14}", d+val));
    }
    public static double MulRound(this double d,double val)
    {
        return double.Parse(string.Format("{0:g14}", d*val));
    }

0

如果你想要0.5而不是.5,可以使用d.ToString("0.##")


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