Utilizzo del formato stringa per mostrare i decimali fino a 2 posizioni o intero semplice


291

Ho un campo prezzi da visualizzare che a volte può essere 100 o 100,99 o 100,9, Quello che voglio è visualizzare il prezzo in 2 cifre decimali solo se i decimali sono inseriti per quel prezzo, ad esempio se è 100, quindi dovrebbe solo mostra 100 non 100.00 e se il prezzo è 100.2 dovrebbe visualizzare 100.20 in modo simile per 100.22 dovrebbe essere lo stesso. Ho cercato su Google e ho trovato alcuni esempi ma non corrispondevano esattamente a ciò che volevo:

// 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: "Quello che voglio è visualizzare il prezzo in 2 cifre decimali solo se vengono immessi i decimali per quel prezzo" - quindi se l'utente digita "100,00" vuoi mostrare "100,00", ma se digita "100" vuoi solo mostrare "100"? - i tipi numerici tracciano solo il valore del numero - non quale delle cifre insignificanti sono state inserite da un utente e quali no - per questo dovrai usare una stringa.
BrainSlugs83

2
@BinaryWorrier Penso che questa domanda possa essere un duplicato, ma ha risposte molto migliori e più complete. L'IMO dovrebbe essere contrassegnato come duplicato di questo.
Ryan Gates,

aggiungi .Replace (". 00", "")
Dave Sumter il

Risposte:


156

Un modo non elegante sarebbe:

var my = DoFormat(123.0);

Con l' DoFormatessere qualcosa di simile:

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

Non elegante, ma lavoro per me in situazioni simili in alcuni progetti.


6
Questa non è davvero la domanda che è stata posta - ma era stata - perché non usare solo string.Format ("{0: 0.00}"). Sostituisci (". 00", "")?
BrainSlugs83

18
@ BrainSlugs83: a seconda del thread corrente CurrentCulture, il separatore decimale potrebbe non esserlo .. A meno che non CultureInfo.InvariantCulturesia usato con string.Format, dovresti controllare il valore di CultureInfo.NumberFormat.NumberDecimalSeparator, e sarebbe una vera PITA. :)
Groo,

@Uwe Keim Cosa succede se ho 60000int e voglio che sia 60.000?
Prashant Pimpale

Questa risposta è un caso di "reinventare una ruota quadrata". Non tiene conto della cultura o del fatto che questo è già stato gestito da .NET.
bytedev,

523

Mi dispiace per aver riattivato questa domanda, ma non ho trovato la risposta giusta qui.

Nella formattazione dei numeri è possibile utilizzare 0come luogo obbligatorio e #come luogo opzionale.

Così:

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

Puoi anche combinare 0con #.

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"

Per questo metodo di formulazione viene sempre utilizzato CurrentCulture. Per alcune Culture .verrà cambiato in ,.

Risposta alla domanda originale:

La soluzione più semplice viene da @Andrew ( qui ). Quindi userei personalmente qualcosa del genere:

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

20
All'inizio, ho pensato che questa dovrebbe essere la risposta, fino a quando non rileggerò più volte la domanda originale. L'OP non è del tutto chiaro cosa vuole esattamente, ma sembra che voglia sempre 2 decimali se qualcuno inserisce una frazione. Quindi, se qualcuno inserisse 1.1 allora vorrebbe 1.10; questo codice non lo farebbe.
Doug S,

40
Oops, l'ho letto di nuovo e hai ragione. Quindi, questa non è la risposta giusta ma almeno qualcuno potrebbe trovarla utile.
Gh61

Che OP necessario può essere raggiunto con questo: stackoverflow.com/a/33180829/2321042
Andrew

Ho appena trovato utile e (in qualche modo) abbinare ciò che fa un BoundField in un GridView con un SqlDouble e nessuna istruzione di formato. Devi indicare il numero massimo che mostrerai. (Vs. BoundField, felice di mostrarne tutti o quanti ne desideri)
fortboise

Sì, questo è stato utile, ma come mostrare solo due decimali se è presente il decimale? cioè se è un numero intero allora non mostra i decimali?
Nigel Fds

64

Questo è un caso d'uso di numero mobile di formattazione comune.

Sfortunatamente, tutte le stringhe di formato a una lettera integrate (ad es. F, G, N) non lo raggiungeranno direttamente.
Ad esempio, num.ToString("F2")mostrerà sempre 2 cifre decimali come 123.40.

Dovrai usare il 0.##modello anche se sembra un po 'prolisso.

Un esempio di codice completo:

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
Ma vuole 123.40, non 123.4.
Andrew,

8
Non risolvere questa domanda ma risolvere la mia. Ho votato questo per venire visualizzato da tutti gli altri.
Emad,

46

Vecchia domanda ma volevo aggiungere l'opzione più semplice secondo me.

Senza migliaia di separatori:

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

Con migliaia di separatori:

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

Lo stesso ma con String.Format :

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

Se ne hai bisogno in molti luoghi , userei questa logica in un metodo di estensione :

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

28

provare

double myPrice = 123.0;

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

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

8

Non so comunque di inserire una condizione nell'identificatore di formato, ma puoi scrivere il tuo formattatore:

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

Ecco un'alternativa al metodo di Uwe Keim, che manterrebbe comunque la stessa chiamata al metodo:

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

Con l' MyCustomFormatessere qualcosa di simile:

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

Questo non ha funzionato per me poiché sembra che TrimEnd abbia una serie di caratteri come {',', '.', ''} Piuttosto che una stringa come ".00" - Vedi msdn.microsoft.com/en-us/ library /
system.string.trimend.aspx

Hai ragione, non sono sicuro di come mi sia perso. Ho aggiornato per funzionare correttamente.
Steve,

5
A seconda del thread corrente CurrentCulture , il separatore decimale potrebbe non esserlo .. A meno che non CultureInfo.InvariantCulturesia usato con string.Format, dovresti controllare il valore di CultureInfo.NumberFormat.NumberDecimalSeparator, che è piuttosto inelegante.
Groo,

6

Semplice codice a una riga:

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

Il problema con questo è se viene eseguito in cui il separatore decimale è una virgola. Controlla i commenti per questa risposta .
Andrew,

6

Se il programma deve essere eseguito rapidamente, chiama value.ToString (formatString) per prestazioni di formattazione delle stringhe ~ 35% più veloci rispetto a $ "{value: formatString}" e string.Format (formatString, value).

Dati

Prestazioni di formattazione di stringhe C # - VS2017 15.4.5

Codice

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

Uscita del codice

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

Riferimenti

Stringhe di formato numerico personalizzate [docs.microsoft.com]

Esempio di grafico a barre dei grafici Qt [doc.qt.io]


5

Temo che non ci sia un formato integrato che lo farà. Dovrai utilizzare un formato diverso a seconda che il valore sia un numero intero o meno. Oppure formatta sempre con 2 cifre decimali e successivamente modifica la stringa per rimuovere eventuali "0" finali.


4

Se nessuna delle altre risposte funziona per te, potrebbe essere perché stai vincolando ContentPropertyun controllo nella OnLoadfunzione, il che significa che non funzionerà:

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

La soluzione è semplice: c'è una ContentStringFormatproprietà in xaml. Quindi quando crei l'etichetta fai questo:

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

O

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

3

qualcosa del genere funzionerà anche:

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

Questo dà una percentuale?

3

Provare:

String.Format("{0:0.00}", Convert.ToDecimal(totalPrice));

2

Per rendere più chiaro il codice in cui ha scritto Kahia (è chiaro ma diventa complicato quando vuoi aggiungere altro testo ad esso) ... prova questa semplice soluzione.

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

Ho dovuto aggiungere il cast extra (decimale) per avere Math.Round confrontare le due variabili decimali.


1

Questo ha funzionato per me!

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

1
Non funziona Vuole che 123.00 venga mostrato come "123" e 123.50 come "123.50".
Andrew,

1

Quando si ha a che fare con decimali provenienti da un database (T-) SQL, si desidera essere in grado di convertire decimali nullable e non nullable con posizioni decimali x ed essere in grado di rivedere facilmente il codice rispetto alle definizioni della tabella - e, naturalmente, visualizzare il giusto numero di decimali per l'utente.

Sfortunatamente, Entity Framework non converte automaticamente qualcosa come un SQL decimal(18,2) in un equivalente .NET con lo stesso numero di cifre decimali (poiché è disponibile solo la cifra decimale con la massima precisione). Devi troncare manualmente le cifre decimali.

Quindi l'ho fatto in questo modo:

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

Esempio di utilizzo:

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)
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.