2 yere kadar ondalık sayı veya basit tam sayı göstermek için Dize Biçimini kullanma


291

Bazen 100 veya 100.99 veya 100.9 olabileceğini göstermek için bir fiyat alanım var, istediğim fiyatı sadece ondalık sayı girilirse 2 ondalık basamakta görüntülemek, örneğin 100 ise 100 değil 100.00 göster ve eğer fiyat 100.2 ise 100.22 için benzer şekilde 100.20 göstermelidir. Google'a gittim ve bazı örneklerle karşılaştım, ancak tam olarak istediğimle eşleşmediler:

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


1
RE: "İstediğim fiyat sadece ondalık basamakları bu fiyat için girilirse 2 ondalık basamakta görüntülemek" - yani kullanıcı "100.00" yazıyorsa "100.00" göstermek istiyorsanız, ama "100" yazarsa sadece "100" ü göstermek mi istiyorsun? - sayı türleri yalnızca sayının değerini izler - bir kullanıcı tarafından önemsiz basamaklardan hangilerinin girildiğini ve hangilerinin girilmediğini - bunun için bir dize kullanmanız gerekir.
BrainSlugs83

2
@BinaryWorrier Bu sorunun yinelenebileceğini düşünüyorum, ancak çok daha iyi ve daha eksiksiz cevapları var. IMO diğeri bunun kopyası olarak işaretlenmelidir.
Ryan Gates

1
sadece .Replace (". 00", "") ekleyin
Dave Sumter

Yanıtlar:


156

Uygun olmayan bir yol:

var my = DoFormat(123.0);

İle DoFormatböyle bir şey söz konusu olur:

public static string DoFormat( double myNumber )
{
    var s = string.Format("{0:0.00}", myNumber);

    if ( s.EndsWith("00") )
    {
        return ((int)myNumber).ToString();
    }
    else
    {
        return s;
    }
}

Zarif değil ama bazı projelerde benzer durumlarda benim için çalışıyor.


6
Bu gerçekten sorulan soru değil - ama olmuştu - neden sadece string.Format ("{0: 0.00}") kullanmıyorsunuz. Değiştirin (". 00", "")?
BrainSlugs83

18
@ BrainSlugs83: geçerli iş parçacığına bağlı olarak CurrentCulture, ondalık ayırıcı olmayabilir .. CultureInfo.InvariantCultureKullanılmadığı sürece , string.Formatdeğerini kontrol etmeniz gerekir CultureInfo.NumberFormat.NumberDecimalSeparatorve bu gerçek bir PITA olacaktır. :)
Groo

@Uwe Keim Ya 60000int varsa ve olmasını istiyorum 60.000?
Prashant Pimpale

Bu cevap, "kare bir tekerleğin yeniden icat edilmesi" durumudur. Kültürü veya bunun .NET tarafından zaten ele alındığı gerçeğini dikkate almaz.
bytedev

523

Bu soruyu yeniden etkinleştirdiğim için üzgünüm, ama burada doğru cevabı bulamadım.

Sayıları biçimlendirirken 0zorunlu bir yer #olarak ve isteğe bağlı bir yer olarak kullanabilirsiniz.

Yani:

// 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"

Ayrıca birleştirebilirsiniz 0ile #.

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"

Bu biçimlendirme yöntemi için her zaman kullanılır CurrentCulture. Bazı Kültürler için .olarak değiştirilecektir ,.

Orijinal sorunun cevabı:

En basit çözüm @Andrew'dan ( burada ) gelir . Ben şahsen şöyle bir şey kullanırdım:

var number = 123.46;
String.Format(number % 1 == 0 ? "{0:0}" : "{0:0.00}", number)

20
İlk başta, orijinal soruyu birkaç kez tekrar okuyana kadar bunun cevap olması gerektiğini düşündüm. OP tam olarak ne istediğini tam olarak açıklamıyor, ancak birisi bir kesire girerse her zaman 2 ondalık basamak istiyor gibi görünüyor. Yani birisi 1.1'e girerse 1.10'u isterdi; bu kod bunu yapmazdı.
Doug S

40
Hata! Tekrar okudum ve haklısın. Yani, bu doğru cevap değil ama en azından birisi bunu faydalı bulabilir.
Gh61

İhtiyaç duyulan OP bu ile elde edilebilir: stackoverflow.com/a/33180829/2321042
Andrew

Ben sadece yararlı buldum ve (biraz) bir GridView BoundField bir SqlDouble ile yaptığı ve hiçbir biçimlendirme talimatı eşleştirme. Göstereceğiniz maksimum # değeri belirtmeniz gerekir. (Vs BoundField, istediğiniz kadar çok veya az göstermekten mutluluk duyarız)
fortboise

Evet, bu yararlı oldu, ancak ondalık varsa yalnızca iki ondalık sayı nasıl gösterilir? yani onun bir tamsayı sonra ondalık göstermez?
Nigel Fds

64

Bu yaygın bir biçimlendirme kayan sayı kullanım durumudur.

Ne yazık ki, tüm yerleşik tek harfli biçim dizeleri (örn. F, G, N) bunu doğrudan başaramaz.
Örneğin, num.ToString("F2")her zaman 2 ondalık basamak gösterir 123.40.

Kullanmanız gerekecek 0.##Biraz ayrıntılı görünse bile deseni .

Tam bir kod örneği:

double a = 123.4567;
double b = 123.40;
double c = 123.00;

string sa = a.ToString("0.##"); // 123.46
string sb = b.ToString("0.##"); // 123.4
string sc = c.ToString("0.##"); // 123

7
Ama 123.4 değil, 123.40 istiyor.
Andrew

8
Bu soruyu değil, benimkini çözüyorum. Bunu herkesin görmesi için destekliyorum.
Emad

46

Eski soru ama bence en basit seçeneği eklemek istedim.

Binlerce ayırıcı olmadan :

value.ToString(value % 1 == 0 ? "F0" : "F2")

İle binlerce ayırıcılar:

value.ToString(value % 1 == 0 ? "N0" : "N2")

Aynı ama String.Format ile :

String.Format(value % 1 == 0 ? "{0:F0}" : "{0:F2}", value) // Without thousands separators
String.Format(value % 1 == 0 ? "{0:N0}" : "{0:N2}", value) // With thousands separators

Birçok yerde ihtiyacınız varsa , bu mantığı bir uzantı yönteminde kullanırsınız :

public static string ToCoolString(this decimal value)
{
    return value.ToString(value % 1 == 0 ? "N0" : "N2"); // Or F0/F2 ;)
}

28

Deneyin

double myPrice = 123.0;

String.Format(((Math.Round(myPrice) == myPrice) ? "{0:0}" : "{0:0.00}"), myPrice);

5
string.Format ((sayı% 1) == 0? "{0: 0}": "{0: 0.00}", sayı);
Patrick

8

Biçim belirleyicisine bir koşul koymak için yine de bilmiyorum, ancak kendi biçimlendiricinizi yazabilirsiniz:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
               // all of these don't work
            Console.WriteLine("{0:C}", 10);
            Console.WriteLine("{0:00.0}", 10);
            Console.WriteLine("{0:0}", 10);
            Console.WriteLine("{0:0.00}", 10);
            Console.WriteLine("{0:0}", 10.0);
            Console.WriteLine("{0:0}", 10.1);
            Console.WriteLine("{0:0.00}", 10.1);

          // works
            Console.WriteLine(String.Format(new MyFormatter(),"{0:custom}", 9));
            Console.WriteLine(String.Format(new MyFormatter(),"{0:custom}", 9.1));
            Console.ReadKey();
        }
    }

    class MyFormatter : IFormatProvider, ICustomFormatter
    {
        public string Format(string format, object arg, IFormatProvider formatProvider)
        {
            switch (format.ToUpper())
            {
                case "CUSTOM":
                    if (arg is short || arg is int || arg is long)
                        return arg.ToString();
                    if (arg is Single || arg is Double)
                        return String.Format("{0:0.00}",arg);
                    break;
                // Handle other
                default:
                    try
                    {
                        return HandleOtherFormats(format, arg);
                    }
                    catch (FormatException e)
                    {
                        throw new FormatException(String.Format("The format of '{0}' is invalid.", format), e);
                    }
            }
            return arg.ToString(); // only as a last resort
        }

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

        public object GetFormat(Type formatType)
        {
            if (formatType == typeof(ICustomFormatter))
                return this;
            return null;
        }
    }
}

6

İşte aynı yöntem çağrısını sürdürecek olan Uwe Keim'in yöntemine bir alternatif:

var example1 = MyCustomFormat(123.1);  // Output: 123.10
var example2 = MyCustomFormat(123.95); // Output: 123.95
var example3 = MyCustomFormat(123);    // Output: 123

İle MyCustomFormatböyle bir şey söz konusu olur:

public static string MyCustomFormat( double myNumber )
{
    var str (string.Format("{0:0.00}", myNumber))
    return (str.EndsWith(".00") ? str.Substring(0, strLastIndexOf(".00")) : str;
}

Bu benim için işe yaramadı, çünkü TrimEnd ".00" gibi bir dize yerine {',', '.', ''} Gibi bir dizi karakter alıyor - Bkz. Msdn.microsoft.com/en-us/ kütüphane / system.string.trimend.aspx
user1069816

Haklısın - bunu nasıl özlediğime emin değilim. Doğru çalışacak şekilde güncelledim.
Steve

5
Geçerli iş parçacığına bağlı olarak CurrentCulture, ondalık ayırıcı olmayabilir .. CultureInfo.InvariantCultureKullanılmadığı sürece , string.Formatdeğerini kontrol etmek zorunda kalacaksınız CultureInfo.NumberFormat.NumberDecimalSeparator, ki bu oldukça yetersizdir.
Groo

6

Basit bir satır kodu:

public static string DoFormat(double myNumber)
{
    return string.Format("{0:0.00}", myNumber).Replace(".00","");
}

Buradaki sorun, ondalık ayırıcının virgül olduğu yerde çalıştırılmasıdır. Bu cevap için yorumları kontrol edin .
Andrew

6

Programınızın hızlı çalışması gerekiyorsa, $ "{value: formatString}" ve string.Format'a (formatString, değer) göre ~% 35 daha hızlı dize biçimlendirme performansı için value.ToString (formatString) öğesini çağırın.

Veri

C # Dize Biçimlendirme Performansı - VS2017 15.4.5

kod

using System;
using System.Diagnostics;

public static class StringFormattingPerformance
{
   public static void Main()
   {
      Console.WriteLine("C# String Formatting Performance");
      Console.WriteLine("Milliseconds Per 1 Million Iterations - Best Of 5");
      long stringInterpolationBestOf5 = Measure1MillionIterationsBestOf5(
          (double randomDouble) =>
          {
             return $"{randomDouble:0.##}";
          });
      long stringDotFormatBestOf5 = Measure1MillionIterationsBestOf5(
          (double randomDouble) =>
          {
             return string.Format("{0:0.##}", randomDouble);
          });
      long valueDotToStringBestOf5 = Measure1MillionIterationsBestOf5(
          (double randomDouble) =>
          {
             return randomDouble.ToString("0.##");
          });
      Console.WriteLine(
$@"            $""{{value:formatString}}"": {stringInterpolationBestOf5} ms
 string.Format(formatString, value): {stringDotFormatBestOf5} ms
       value.ToString(formatString): {valueDotToStringBestOf5} ms");
   }

   private static long Measure1MillionIterationsBestOf5(
       Func<double, string> formatDoubleUpToTwoDecimalPlaces)
   {
      long elapsedMillisecondsBestOf5 = long.MaxValue;
      for (int perfRunIndex = 0; perfRunIndex < 5; ++perfRunIndex)
      {
         var random = new Random();
         var stopwatch = Stopwatch.StartNew();
         for (int i = 0; i < 1000000; ++i)
         {
            double randomDouble = random.NextDouble();
            formatDoubleUpToTwoDecimalPlaces(randomDouble);
         }
         stopwatch.Stop();
         elapsedMillisecondsBestOf5 = Math.Min(
            elapsedMillisecondsBestOf5, stopwatch.ElapsedMilliseconds);
      }
      return elapsedMillisecondsBestOf5;
   }
}

Kod Çıkışı

C# String Formatting Performance
Milliseconds Per 1 Million Iterations - Best Of 5
            $"{value:formatString}": 419 ms
 string.Format(formatString, value): 419 ms
       value.ToString(formatString): 264 ms

Referanslar

Özel Sayısal Biçim Dizeleri [docs.microsoft.com]

Qt Grafikleri BarChart Örneği [doc.qt.io]


5

Korkarım bunu yapacak yerleşik bir format yoktur. Değerin bir tam sayı olup olmamasına bağlı olarak farklı bir biçim kullanmanız gerekecektir. Veya her zaman 2 ondalık basamağa biçimlendirin ve sonradan ".00" karakterini kaldırmak için dizeyi değiştirin.


4

Diğer yanıtların hiçbiri sizin için işe yaramıyorsa, bunun nedeni işlevdeki ContentPropertybir denetimi bağlamanızdır;OnLoad

private void UserControl_Load(object sender, RoutedEventArgs e)
{
  Bind.SetBindingElement(labelName, String.Format("{0:0.00}", PropertyName), Label.ContentProperty) 
}

Çözüm basit: ContentStringFormatxaml'de bir özellik var . Etiketi oluştururken şunu yapın:

//if you want the decimal places definite
<Label Content="0" Name="labelName" ContentStringFormat="0.00"/>

Veya

//if you want the decimal places to be optional
<Label Content="0" Name="labelName" ContentStringFormat="0.##"/>

3

böyle bir şey de işe yarayacak:

String.Format("{0:P}", decimal.Parse(Resellers.Fee)).Replace(".00", "")

Bu yüzde mi veriyor?


2

Kahia'nın yazdığı kodu daha açık hale getirmek için (açıktır, ancak daha fazla metin eklemek istediğinizde zorlaşır) ... bu basit çözümü deneyin.

if (Math.Round((decimal)user.CurrentPoints) == user.CurrentPoints)
     ViewBag.MyCurrentPoints = String.Format("Your current Points: {0:0}",user.CurrentPoints);
else
     ViewBag.MyCurrentPoints = String.Format("Your current Points: {0:0.0}",user.CurrentPoints);

Math.Round iki ondalık değişken karşılaştırmak için ekstra döküm (ondalık) eklemek zorunda kaldı.


1

Bu benim için çalıştı!

String amount= "123.0000";
String.Format("{0:0.##}", amount);      // "123.00"

1
Bu işe yaramıyor. 123.00'ın "123" ve 123.50'nin "123.50" olarak gösterilmesini istiyor.
Andrew

1

Bir (T-) SQL veritabanından gelen ondalık sayılarla uğraşırken, nullable ve nullable ondalık sayıları x ondalık basamakla dönüştürebilir ve kodu tablo tanımlarınıza göre kolayca gözden geçirebilirsiniz - ve elbette, kullanıcıya doğru ondalık sayı.

Ne yazık ki, Entity Framework otomatik olarak SQL gibi bir şeyi dönüştürmüyor decimal(18,2) aynı sayıda ondalık basamağa sahip bir .NET eşdeğerine (tam hassasiyetle yalnızca ondalık olduğu için). Ondalık basamakları manuel olarak kısaltmanız gerekir.

Bu şekilde yaptım:

public static class Extensions
{
    public static string ToStringDecimal(this decimal d, byte decimals)
    {
        var fmt = (decimals>0) ? "0." + new string('0', decimals) : "0";
        return d.ToString(fmt);
    }

    public static string ToStringDecimal(this decimal? d, byte decimals)
    {
        if (!d.HasValue) return "";
        return ToStringDecimal(d.Value, decimals);
    }
}

Örnek Kullanım:

void Main()
{
    decimal d = (decimal)1.2345;
    decimal? d2 = null; 

    Console.WriteLine(d.ToStringDecinal(2)); // prints: "1.23" (2 decimal places)
    Console.WriteLine(d.ToStringDecinal(0)); // prints: "1" (show integer number)
    Console.WriteLine(d2.ToStringDecimal(2)); // prints: "" (show null as empty string)
}
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.