C # Double - İki ondalık basamak içeren ancak yuvarlamayan ToString () biçimlendirmesi


153

Yalnızca iki ondalık basamak olacak Doubleşekilde a String# 'yı C # biçiminde nasıl biçimlendirebilirim ?

Ben kullanırsanız String.Format("{0:0.00}%", myDoubleValue)sayı daha sonra yuvarlak olduğunu ve herhangi bir yuvarlanması olmadan basit bir kesiğinin istiyorum. Ayrıca dönüşümün Stringkültüre duyarlı olmasını istiyorum .


"Kültüre duyarlı" ile ne demek istiyorsun? Bu, biçimlendirmenin sonucunun programcı tarafından sağlanan bir kültür değerine bağlı olarak değişmesi gerektiği anlamına mı geliyor? Veya geçerli iş parçacığı için varsayılan olan kültürü kullanmak istiyor musunuz?
CesarGon

Yanıtlar:


204

Aşağıdakileri kullanıyorum:

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

Örneğin:

Sayı 50.947563 ise ve aşağıdakileri kullanırsanız, aşağıdakiler gerçekleşir:

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

Ve cevabınız kesildi, şimdi dizeyi biçimlendirmek için şunları yapın:

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

3
-1 Kültüre duyarlı biçimlendirmeyi string.Formatdizeyi biçimlendiren aynı adımda yapabilirsiniz. Cevabımı aşağıda görebilirsiniz.
CesarGon

1
Bu harika. Umarım yorumum o kadar aptalca görünmüyor. :-) O zaman downvote'umu değiştireceğim.
CesarGon

1
Bana göre, dize biçimlendirmedeki çözüm inanılmaz derecede basit olduğu için, kesme daha zor oldu.
Kyle Rosendo

1
Maalesef, 1'den az olduğunda çözümünüz işe yaramıyor: Göstermek için: 0.97, Bu durum için herhangi bir geçici çözüm var mı?
Ali Dehghan

2
@Jon yuvarladığı için çalışmayacak - OP kesilmesini istiyor (ve yuvarlak değil). Fark incedir.
BKSpurgeon

102

Aşağıdakiler sayıları yuvarlar , ancak sayesinde en fazla 2 ondalık basamak gösterir (arkadaki sıfırları kaldırarak) .##.

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
Bu işe yaramıyor. 0.2415999 ile deneyin. Bu çözümler keser, yuvarlar.
BJury

5
Vay, çok fazla oy ve yine de yuvarlama kullanıyor. Yuvarlamanın talep edilen en yakın ondalık basamağa doğru gittiğini belirtmek gerekebilir, oysa kesilme istenen en yakın ondalık basamağın ardından kesiliyor.
mysticcoder

1
@ mysticcoder Sanırım cevabım o kadar çok oy alıyor ki ops sorusuna aynı şekilde bir Google aramasında yaptığım gibi geliyor, takip eden sıfırları kaldırmak istiyor ve ops sorununun yuvarlanma arzusunu aramıyorlar. Cevabımı
Brian Ogden

@BrianOgden - Hayır, lütfen silmeyin. Buraya cevabınızı aramak için geldim. +1
Roberto

35

Önce kesmenizi ve daha sonra biçimlendirmenizi öneririm:

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);

2 basamaklı kesik için 100 sabitini kullanın; 1'i ve ardından istediğiniz ondalık basamaktan sonra sıfırları kullanın. Biçimlendirme sonucunu ayarlamak için gereken kültür adını kullanın.


Bunun yerine new CultureInfo("de-DE")statik özelliği kullanmanız gerektiğini düşünüyorumCulture.InvariantCulture
vchan


13

price.ToString("0.00") Baştaki 0'ları almak için kullanıyorum


6

Kyle Rozendo tarafından ifade edildiği gibi c # işlevi:

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

Yuvarlanacak ve atılacak ek bir ondalık sayı eklemeye ne dersiniz:

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

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

3
Çalışmayan bir cevabın (bugün itibariyle) 60 oylama
yapması komik

5
Yuvarlamanın kesme üzerinde birden fazla rakamı etkilemesi durumunda bu çalışmaz. Örneğin, 0.199999, 0.19 yerine bu kodla 0.20 olarak sonuçlanacaktır.
Bernem

4

Bu benim için çalışıyor

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

2

Bu eski bir konu olduğunu biliyorum ama ben sadece bunu yapmak zorunda kaldı. Buradaki diğer yaklaşımlar işe yararken, birçok çağrıyı etkilemek için kolay bir yol istedim string.format. Yani Math.Truncatetüm çağrıları eklemek gerçekten iyi bir seçenek değildi. Ayrıca, biçimlendirmenin bir kısmı bir veritabanında saklandığından, daha da kötüleştirdi.

Böylece, biçimlendirme dizesine kısaltma eklemek için izin verecek bir özel format sağlayıcı yaptı, örneğin:

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

Uygulama oldukça basittir ve diğer gereksinimlere kolayca genişletilebilir.

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;
    }
}

2

Xamarin Forms ile bu sorunu vardı ve bu ile çözüldü:

percent.ToString("0.##"+"%")

1

Para birimini göstermek için neye değer olduğunu kullanabilirsiniz "C":

double cost = 1.99;
m_CostText.text = cost.ToString("C"); /*C: format as currentcy */

Çıktı: $1.99


0

Ayrıca kendi IFormatProvider'ınızı da yazabilirsiniz , ancak sonunda gerçek kesmeyi yapmanın bir yolunu düşünmeniz gerektiğini düşünüyorum.

.NET Framework ayrıca özel biçimlendirmeyi de destekler. Bu genellikle IFormatProvider ve ICustomFormatter öğelerini uygulayan bir biçimlendirme sınıfının oluşturulmasını içerir . (msdn)

En azından kolayca tekrar kullanılabilir.

CodeProject'de kendi IFormatProvider / ICustomFormatter'ınızı nasıl uygulayacağınızla ilgili bir makale var . Bu durumda, mevcut bir sayısal formatı "genişletmek" en iyi bahis olabilir. Çok zor görünmüyor.


0

Aşağıdaki yalnızca String özelliğini kullanan görüntüleme için kullanılabilir.

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

Bu "123.46" verecektir. Soru, özellikle yuvarlama yapılmasını istemiyor.
19'da Tobberoth

0

Çözüm:

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

(indexOfP + 1) +2 (bu sayı kaç tane korumak istediğinize bağlıdır. İki tane veriyorum çünkü soru sahibi istiyor.)


0

Ayrıca sisteminizin CultureInformation bilgisine de dikkat edin . İşte benim yuvarlama olmadan benim çözüm.

Bu örnekte, MyValue değişkenini çift ​​olarak tanımlamanız yeterlidir . Sonuç olarak biçimlendirilmiş değerinizi NewValue dize değişkeninde alırsınız .

Not - Ayrıca C # ifadesini kullanarak ayarlayın:

using System.Globalization;  

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

string NewValue = MyValue.ToString(MyFormat);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.