Doppio C #: formattazione ToString () con due cifre decimali ma nessun arrotondamento


153

Come posso formattare da Doublea a Stringin C # in modo da avere solo due cifre decimali?

Se uso String.Format("{0:0.00}%", myDoubleValue)il numero viene quindi arrotondato e voglio un troncato semplice senza alcun arrotondamento. Voglio anche che la conversione Stringsia sensibile alla cultura.


Cosa intendi con "cultura sensibile"? Ciò significa che il risultato della formattazione deve variare a seconda del valore di cultura fornito dal programmatore? O vuoi usare qualsiasi cultura sia l'impostazione predefinita per il thread corrente?
CesarGon,

Risposte:


204

Io uso il seguente:

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

Per esempio:

Se il numero è 50.947563 e si utilizza quanto segue, si verificherà quanto segue:

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

E c'è la tua risposta troncata, ora per formattare la stringa è sufficiente fare quanto segue:

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

3
-1 È possibile eseguire la formattazione sensibile alla cultura nello stesso string.Formatpassaggio che formatta la stringa. Vedi la mia risposta qui sotto.
CesarGon,

1
È fantastico. Spero che il mio commento non sembri così sciocco ora. :-) Allora cambierò il mio voto negativo.
CesarGon,

1
Per me lo ha fatto, poiché la soluzione sulla formattazione delle stringhe è incredibilmente semplice, il troncamento è stato più complicato.
Kyle Rosendo,

1
Sfortunatamente la tua soluzione non funziona quando il numero è inferiore a 1, per illustrare: 0.97, c'è qualche soluzione alternativa per questa situazione?
Ali Dehghan,

2
@Jonny che non funzionerà perché arrotonda - OP vuole che si tronchi (e non arrotondare). La differenza è sottile.
BKSpurgeon,

102

Quanto segue arrotonda i numeri, ma mostra solo fino a 2 cifre decimali (rimuovendo eventuali zeri finali), grazie a .##.

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
Questo non funziona Provalo con 0.2415999. Questa soluzione arrotonda, non tronca.
Giuria

5
Caspita, tanti voti positivi eppure sta usando l'arrotondamento. Potrebbe essere necessario sottolineare che l'arrotondamento si sta dirigendo verso il decimale più vicino richiesto, mentre il troncamento si interrompe dopo il decimale più vicino richiesto.
mysticcoder

1
@mysticcoder Immagino che la mia risposta ottenga così tanti voti positivi perché arrivano alla domanda sulle operazioni in una ricerca su Google nello stesso modo in cui ho cercato di rimuovere gli zeri finali e non cercare il desiderio di arrotondamento della domanda sulle operazioni. Immagino che dovrei cancellare la mia risposta ...
Brian Ogden

@BrianOgden - No, per favore non cancellare. Sono arrivato qui in cerca della tua risposta. +1
Roberto

35

Ti suggerisco di troncare prima, quindi formattare:

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

Utilizzare la costante 100 per 2 cifre troncate; usa un 1 seguito da tanti zeri quante cifre dopo il punto decimale che desideri. Utilizzare il nome della cultura necessario per regolare il risultato di formattazione.


Penso che invece di new CultureInfo("de-DE")usare la proprietà staticaCulture.InvariantCulture
vchan


13

io uso price.ToString("0.00") per ottenere gli 0 iniziali


6

La funzione c #, espressa da Kyle Rozendo:

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

Che ne dici di aggiungere un altro decimale che deve essere arrotondato e poi scartato:

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

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

3
È divertente come una risposta non funzionante abbia 60 voti positivi (ad oggi), e questa soluzione abbastanza semplice e antiproiettile ne ha solo una ...
Arthur Kazykhanov,

5
Ciò non funzionerà nel caso in cui l'arrotondamento influisca su più di una cifra sopra il valore soglia. Ad esempio 0,199999 finirà con 0,20 con questo codice, anziché 0,19.
Bernem,

4

Questo funziona per me

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

2

So che questo è un vecchio thread, ma ho dovuto farlo. Mentre gli altri approcci qui funzionano, volevo un modo semplice per essere in grado di influenzare molte chiamate string.format. Quindi aggiungere Math.Truncatea tutte le chiamate non era davvero una buona opzione. Inoltre, poiché una parte della formattazione è archiviata in un database, è stato anche peggiorato.

Pertanto, ho creato un provider di formati personalizzati che mi consentirebbe di aggiungere il troncamento alla stringa di formattazione, ad esempio:

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

L'implementazione è piuttosto semplice ed è facilmente estendibile ad altri requisiti.

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

Ho avuto quel problema con Xamarin Forms e l'ho risolto con questo:

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

1

Per quanto vale, per mostrare la valuta, puoi usare "C":

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

Produzione: $1.99


0

Potresti anche scrivere il tuo IFormatProvider , anche se suppongo che alla fine dovresti pensare a un modo per eseguire il troncamento effettivo.

.NET Framework supporta anche la formattazione personalizzata. Ciò comporta in genere la creazione di una classe di formattazione che implementa sia IFormatProvider che ICustomFormatter . (MSDN)

Almeno sarebbe facilmente riutilizzabile.

C'è un articolo su come implementare il proprio IFormatProvider / ICustomFormatter qui su CodeProject . In questo caso, "estendere" un formato numerico esistente potrebbe essere la scommessa migliore. Non sembra troppo difficile.


0

Di seguito può essere utilizzato solo per la visualizzazione che utilizza la proprietà di String ..

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

Questo darà "123.46". La domanda in particolare non richiede arrotondamenti.
Tobberoth,

0

Soluzione:

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

(indexOfP + 1) +2 (questo numero dipende da quanti numeri vuoi conservare. Ne do due perché il proprietario della domanda vuole.)


0

Notare anche CultureInformation del tuo sistema. Qui la mia soluzione senza arrotondamento.

In questo esempio devi solo definire la variabile MyValue come doppia. Di conseguenza si ottiene il valore formattato nella variabile stringa NewValue .

Nota: imposta anche C # usando l'istruzione:

using System.Globalization;  

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

string NewValue = MyValue.ToString(MyFormat);
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.