C#Double-ToString()格式为两位小数,但不舍入


153

如何在C#中将Doublea 格式化为a String,以便仅保留两位小数?

如果我使用String.Format("{0:0.00}%", myDoubleValue)该数字,则将其四舍五入,并且我希望不进行任何舍入而进行简单的截断。我也希望转换对String文化敏感。


您对“文化敏感”是什么意思?这是否意味着格式化的结果必须根据程序员提供的文化价值而有所不同?还是要使用当前线程默认的区域性?
CesarGon

Answers:


204

我使用以下内容:

double x = Math.Truncate(myDoubleValue * 100) / 100;

例如:

如果数字是50.947563,并且您使用以下内容,则会发生以下情况:

- Math.Truncate(50.947563 * 100) / 100;
- Math.Truncate(5094.7563) / 100;
- 5094 / 100
- 50.94

而且您的答案被截断了,现在只需执行以下操作即可格式化字符串:

string s = string.Format("{0:N2}%", x); // No fear of rounding and takes the default number format

3
-1您可以在格式化string.Format字符串的同一步骤中执行对区域性敏感的格式化。请参阅下面的答案。
CesarGon

1
那很棒。我希望我的评论现在看起来不会那么傻。:-)然后,我将更改我的投票权。
CesarGon 2010年

1
对我来说确实如此,因为字符串格式的解决方案非常简单,所以截断更加棘手。
凯尔·罗森多

1
不幸的是,当数字小于1时,您的解决方案无法解决问题,例如:0.97,这种情况是否有解决方法?
Ali Dehghan 2014年

2
@Jonny不能运行,因为它会四舍五入-OP希望将其截断(而不是四舍五入)。区别是微妙的。
BKSpurgeon '19

102

以下代码将数字四舍五入,但是最多显示两位小数(删除所有尾随零).##

decimal d0 = 24.154m;
decimal d1 = 24.155m;
decimal d2 = 24.1m;
decimal d3 = 24.0m;

d0.ToString("0.##");   //24.15
d1.ToString("0.##");   //24.16 (rounded up)
d2.ToString("0.##");   //24.1  
d3.ToString("0.##");   //24

http://dobrzanski.net/2009/05/14/c-decimaltostring-and-how-to-get-rid-of-trailing-zeros/


12
这行不通。尝试使用0.2415999。此解决方案是舍入而不是截断。
BJury

5
哇,这么多的赞成票,却在使用四舍五入。可能有必要指出,四舍五入正朝着所请求的最接近的小数位前进,而截断则是在所请求的最接近的小数位之后斩波。
mysticcoder 2015年

1
@mysticcoder我猜我的答案获得了很多好评,因为它们以与我相同的方式进入Google搜索中的ops问题,试图删除尾随的零,而不是在寻找ops问题的舍入期望。我想我应该删除答案...
布赖恩·奥格登

@BrianOgden-不,请不要删除。我到达这里寻找您的答案。+1
罗伯托

35

我建议您先截断,然后格式化:

double a = 123.4567;
double aTruncated = Math.Truncate(a * 100) / 100;
CultureInfo ci = new CultureInfo("de-DE");
string s = string.Format(ci, "{0:0.00}%", aTruncated);

使用常数100截断2位数字;在您想要的小数点后使用1,后跟任意数量的零。使用您需要的区域性名称来调整格式结果。


我认为不是的new CultureInfo("de-DE"),你应该使用静态属性Culture.InvariantCulture
vchan



6

由Kyle Rozendo表示的c#函数:

string DecimalPlaceNoRounding(double d, int decimalPlaces = 2)
{
    d = d * Math.Pow(10, decimalPlaces);
    d = Math.Truncate(d);
    d = d / Math.Pow(10, decimalPlaces);
    return string.Format("{0:N" + Math.Abs(decimalPlaces) + "}", d);
}

5

如何添加一个要舍入然后舍弃的额外小数点:

var d = 0.241534545765;
var result1 = d.ToString("0.###%");

var result2 = result1.Remove(result1.Length - 1);

3
有趣的是,一个无效的答案如何获得60票赞成(截至今天),而这个非常简单且防弹的解决方案只有一个....
Arthur Kazykhanov

5
如果四舍五入影响截止点以上一位以上,则此操作将无效。例如,此代码的0.199999最终将是0.20,而不是0.19。
伯南姆'18

4

这对我有用

string prouctPrice = Convert.ToDecimal(String.Format("{0:0.00}", Convert.ToDecimal(yourString))).ToString();

2

我知道这是一个旧线程,但是我只需要这样做。尽管这里的其他方法可行,但我希望有一种简单的方法来影响对的大量调用string.format。因此,Math.Truncate在所有呼叫中加入并不是一个好选择。同样,由于某些格式存储在数据库中,因此甚至更糟。

因此,我制作了一个自定义格式提供程序,该提供程序将允许我在格式设置字符串中添加截断,例如:

string.format(new FormatProvider(), "{0:T}", 1.1299); // 1.12
string.format(new FormatProvider(), "{0:T(3)", 1.12399); // 1.123
string.format(new FormatProvider(), "{0:T(1)0,000.0", 1000.9999); // 1,000.9

该实现非常简单,并且可以轻松扩展到其他要求。

public class FormatProvider : IFormatProvider, ICustomFormatter
{
    public object GetFormat(Type formatType)
    {
        if (formatType == typeof (ICustomFormatter))
        {
            return this;
        }
        return null;
    }

    public string Format(string format, object arg, IFormatProvider formatProvider)
    {
        if (arg == null || arg.GetType() != typeof (double))
        {
            try
            {
                return HandleOtherFormats(format, arg);
            }
            catch (FormatException e)
            {
                throw new FormatException(string.Format("The format of '{0}' is invalid.", format));
            }
        }

        if (format.StartsWith("T"))
        {
            int dp = 2;
            int idx = 1;
            if (format.Length > 1)
            {
                if (format[1] == '(')
                {
                    int closeIdx = format.IndexOf(')');
                    if (closeIdx > 0)
                    {
                        if (int.TryParse(format.Substring(2, closeIdx - 2), out dp))
                        {
                            idx = closeIdx + 1;
                        }
                    }
                    else
                    {
                        throw new FormatException(string.Format("The format of '{0}' is invalid.", format));
                    }
                }
            }
            double mult = Math.Pow(10, dp);
            arg = Math.Truncate((double)arg * mult) / mult;
            format = format.Substring(idx);
        }

        try
        {
            return HandleOtherFormats(format, arg);
        }
        catch (FormatException e)
        {
            throw new FormatException(string.Format("The format of '{0}' is invalid.", format));
        }
    }

    private string HandleOtherFormats(string format, object arg)
    {
        if (arg is IFormattable)
        {
            return ((IFormattable) arg).ToString(format, CultureInfo.CurrentCulture);
        }
        return arg != null ? arg.ToString() : String.Empty;
    }
}



0

您也可以编写自己的IFormatProvider,尽管我想最终您必须考虑一种进行实际截断的方法。

.NET Framework也支持自定义格式。这通常涉及创建同时实现IFormatProvider和ICustomFormatter的格式化类。(msdn)

至少它将很容易重用。

在CodeProject上有一篇关于如何实现自己的IFormatProvider / ICustomFormatter的文章。在这种情况下,“扩展”现有数字格式可能是最好的选择。它看起来并不难。


0

以下仅可用于使用String ..属性的显示。

double value = 123.456789;
String.Format("{0:0.00}", value);

这将得到“ 123.46”。该问题专门要求不进行四舍五入。
Tobberoth

0

解:

var d = 0.123345678; 
var stringD = d.ToString(); 
int indexOfP = stringD.IndexOf("."); 
var result = stringD.Remove((indexOfP+1)+2);

(indexOfP + 1)+2(此数字取决于您要保留多少个数字。由于问题所有者想要,我给它两个。)


0

另请注意您系统的CultureInformation。这里我的解决方案没有四舍五入。

在此示例中,您只需要将变量MyValue定义为double。结果,您在字符串变量NewValue中获得了格式化的值。

注意-还要设置C#using语句:

using System.Globalization;  

string MyFormat = "0";
if (MyValue.ToString (CultureInfo.InvariantCulture).Contains (CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator))
   {
      MyFormat += ".00";
   }

string NewValue = MyValue.ToString(MyFormat);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.