C # Double - ToString () Formatierung mit zwei Dezimalstellen, aber ohne Rundung

152

Wie formatiere ich Doublea Stringin C # so, dass nur zwei Dezimalstellen vorhanden sind?

Wenn ich String.Format("{0:0.00}%", myDoubleValue)die Zahl benutze, wird sie gerundet und ich möchte ein einfaches Abschneiden ohne Rundung. Ich möchte auch, dass die Konvertierung Stringkulturell sensibel ist.

kjv
quelle
Was meinst du mit "kultursensitiv"? Bedeutet das, dass das Ergebnis der Formatierung abhängig von einem vom Programmierer bereitgestellten Kulturwert variieren muss? Oder möchten Sie die Standardkultur für den aktuellen Thread verwenden?
CesarGon

Antworten:

204

Ich benutze folgendes:

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

Zum Beispiel:

Wenn die Nummer 50.947563 lautet und Sie Folgendes verwenden, geschieht Folgendes:

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

Und da ist Ihre Antwort abgeschnitten. Um die Zeichenfolge zu formatieren, gehen Sie einfach wie folgt vor:

string s = string.Format("{0:N2}%", x); // No fear of rounding and takes the default number format
Kyle Rosendo
quelle
3
-1 Sie können die kulturabhängige Formatierung in demselben string.FormatSchritt durchführen, in dem die Zeichenfolge formatiert wird. Siehe meine Antwort unten.
CesarGon
1
Das ist großartig. Ich hoffe, mein Kommentar sieht jetzt nicht so albern aus. :-) Ich werde dann meine Ablehnung ändern.
CesarGon
1
Für mich war das Abschneiden schwieriger, da die Lösung für die Formatierung von Zeichenfolgen unglaublich einfach ist.
Kyle Rosendo
1
Leider funktioniert Ihre Lösung nicht, wenn die Anzahl kleiner als 1 ist, um Folgendes zu veranschaulichen: 0,97, Gibt es eine Problemumgehung für diese Situation?
Ali Dehghan
2
@Jonny das funktioniert nicht, weil es rundet - OP möchte, dass es abgeschnitten wird (und nicht rundet). Der Unterschied ist subtil.
BKSpurgeon
102

Die folgenden Runden der Zahlen, sondern zeigt nur bis zu 2 Dezimalstellen (Entfernen aller nachfolgenden Nullen), dank .##.

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/

Brian Ogden
quelle
12
Das funktioniert nicht. Versuchen Sie es mit 0.2415999. Diese Lösung rundet, nicht abschneidet.
BJury
5
Wow, so viele Stimmen und doch wird gerundet. Es kann notwendig sein, darauf hinzuweisen, dass die Rundung auf die nächste angeforderte Dezimalstelle zusteuert, während das Abschneiden nach der nächstgelegenen angeforderten Dezimalstelle abbricht.
Mysticcoder
1
@mysticcoder Ich denke, meine Antwort erhält so viele positive Stimmen, weil sie in einer Google-Suche genauso wie ich zur Ops-Frage kommen, um nachfolgende Nullen zu entfernen und nicht nach dem Rundungswunsch der Ops-Frage zu suchen. Ich denke, ich sollte meine Antwort löschen ...
Brian Ogden
@BrianOgden - Nein, bitte nicht löschen. Ich bin hier angekommen und habe nach deiner Antwort gesucht. +1
Roberto
35

Ich schlage vor, Sie schneiden zuerst ab und formatieren dann:

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

Verwenden Sie die Konstante 100 für 2 abgeschnittene Stellen. Verwenden Sie eine 1 gefolgt von so vielen Nullen wie Ziffern nach dem gewünschten Dezimalpunkt. Verwenden Sie den Kulturnamen, den Sie zum Anpassen des Formatierungsergebnisses benötigen.

CesarGon
quelle
Ich denke, dass Sie stattdessen new CultureInfo("de-DE")die statische Eigenschaft verwenden solltenCulture.InvariantCulture
vchan
15

Verwenden Sie für die einfachste Methode Zeichenfolgen im numerischen Format:

double total = "43.257"
MessageBox.Show(total.ToString("F"));
Harambe Kampfhubschrauber
quelle
2
Tatsächlich rundet
elvin
13

Ich benutze price.ToString("0.00") , um die führenden Nullen zu bekommen

CMS
quelle
6

Die c # -Funktion, ausgedrückt von 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);
}
maxp
quelle
5

Wie wäre es mit einer zusätzlichen Dezimalstelle, die gerundet und dann verworfen werden soll:

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

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

quelle
3
Es ist lustig, wie eine nicht funktionierende Antwort 60 Stimmen hat (Stand heute), und diese ziemlich einfache und kugelsichere Lösung hat nur eine ...
Arthur Kazykhanov
5
Dies funktioniert nicht, wenn die Rundung mehr als eine Ziffer über dem Grenzwert betrifft. Zum Beispiel wird 0.199999 mit diesem Code als 0.20 anstelle von 0.19 angezeigt.
Bernem
4

Das funktioniert bei mir

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

Ich weiß, dass dies ein alter Thread ist, aber ich musste das einfach tun. Während die anderen Ansätze hier funktionieren, wollte ich einen einfachen Weg, um viele Anrufe bei beeinflussen zu können string.format. Das Hinzufügen Math.Truncatezu allen Anrufen zu war also keine wirklich gute Option. Da ein Teil der Formatierung in einer Datenbank gespeichert ist, wurde dies noch schlimmer.

Daher habe ich einen benutzerdefinierten Formatanbieter erstellt, mit dem ich der Formatierungszeichenfolge Kürzungen hinzufügen kann, z.

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

Die Implementierung ist ziemlich einfach und kann leicht auf andere Anforderungen erweitert werden.

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;
    }
}
BJury
quelle
2

Ich hatte dieses Problem mit Xamarin Forms und löste es damit:

percent.ToString("0.##"+"%")
Diego Sanchez
quelle
1

Um die Währung anzuzeigen, können Sie Folgendes verwenden "C":

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

Ausgabe: $1.99

Roozbeh Zabihollahi
quelle
0

Sie könnten auch Ihren eigenen IFormatProvider schreiben , obwohl Sie sich wahrscheinlich irgendwann überlegen müssen , wie Sie die eigentliche Kürzung vornehmen können.

Das .NET Framework unterstützt auch benutzerdefinierte Formatierungen. Dies beinhaltet normalerweise die Erstellung einer Formatierungsklasse, die sowohl IFormatProvider als auch ICustomFormatter implementiert . (msdn)

Zumindest wäre es leicht wiederverwendbar.

Hier bei CodeProject finden Sie einen Artikel darüber, wie Sie Ihren eigenen IFormatProvider / ICustomFormatter implementieren . In diesem Fall ist das "Erweitern" eines vorhandenen numerischen Formats möglicherweise die beste Wahl. Es sieht nicht zu schwer aus.

Benny Jobigan
quelle
0

Das Folgende kann nur für die Anzeige verwendet werden, die die Eigenschaft von String verwendet.

double value = 123.456789;
String.Format("{0:0.00}", value);
Md. Shafiqur Rahman
quelle
Dies ergibt "123,46". Die Frage verlangt ausdrücklich keine Rundung.
Tobberoth
0

Lösung:

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

(indexOfP + 1) +2 (Diese Zahl hängt davon ab, wie viele Zahlen Sie beibehalten möchten. Ich gebe zwei, weil der Frageninhaber dies wünscht.)

劉鎮 瑲
quelle
0

Beachten Sie auch die CultureInformation Ihres Systems. Hier meine Lösung ohne Rundung.

In diesem Beispiel müssen Sie nur die Variable MyValue als double definieren. Als Ergebnis erhalten Sie Ihren formatierten Wert in der Zeichenfolgenvariablen NewValue .

Hinweis - Setzen Sie auch die Anweisung 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);
Daniel
quelle