2009-09-15 8 views
10

Jak mogę skrócić wiodącą cyfrę podwójnej wartości w języku C#, Próbowałem Math.Round (doublevalue, 2), ale nie podając wymaganego wyniku. i nie znalazłem żadnej innej metody w klasie Math.Skrócić numer cyfry podwójnej wartości w C#

Na przykład mam wartość 12.123456789 i potrzebuję tylko 12.12.

+3

jaki powinien być wynik, gdy dajesz 12.12890? – rahul

+0

Co ** phoenix ** pyta: czy chcesz zaokrąglić go do 12.13, czy po prostu przyciąć do 12.12 ...? – awe

+0

Yes @awe. To dobrze – rahul

Odpowiedz

25

EDYCJA: Wskazano, że te podejścia mają wartość zamiast skracania. Naprawdę trudno jest obciąć wartość double, ponieważ nie jest to właściwa baza ... ale obcięcie wartości decimal jest bardziej realistyczne.

Należy użyć odpowiedniego ciągu formatów: custom lub standard, np.

string x = d.ToString("0.00"); 

lub

string x = d.ToString("F2"); 

Warto mieć świadomość, że wartość dwukrotnie sam nie „wie” ile miejsc po przecinku ma. Tylko wtedy, gdy przekształcisz go w ciąg znaków, naprawdę ma to sens. Użycie Math.Round otrzyma najbliższą podwójną wartość do x.xx00000 (jeśli widzisz co mam na myśli), ale prawie na pewno nie będzie to dokładna wartość x.xx00000 ze względu na sposób działania binarnych typów zmiennoprzecinkowych.

Jeśli potrzebujesz tego do wszystkiego, co jest inne niż formatowanie ciągów, powinieneś rozważyć użycie zamiast tego decimal. Co właściwie oznacza wartość?

Mam artykuły na temat binary floating point i decimal floating point w .NET, które mogą okazać się przydatne.

+0

Dzięki za odpowiedź, nie chcę konwertować wartości w ciągu, a następnie z powrotem do podwójnego ponownie, muszę przechowywać wartość jak . var newVal = Math.Round (oldValue, 2) lub inna funkcja. – Firoz

+3

@Firoz: na ciąg i powrót do podwójności nie pomogą ci w każdym razie: jeśli double nie może dokładnie oznaczać "12.34", wtedy * uzyska * dodatkowe wartości dziesiętne. Zwykle nie jest możliwe zapisanie podwójnego z tylko dwoma miejscami dziesiętnymi. –

+0

@Firoz: Hans ma absolutną rację. Dodaję kilka linków w mojej odpowiedzi ... –

0

numer obiektu = 12.123345534;
string.Format ({"0:00"}, number.ToString());

15

Co próbowaliście? To działa zgodnie z oczekiwaniami dla mnie:

double original = 12.123456789; 

double truncated = Math.Truncate(original * 100)/100; 

Console.WriteLine(truncated); // displays 12.12 
3

Ten kod ....

double x = 12.123456789; 
Console.WriteLine(x); 
x = Math.Round(x, 2); 
Console.WriteLine(x); 

zwraca ten ....

12.123456789 
12.12 

Jaki jest pożądany wynik, że jest inaczej?

Jeśli chcesz zachować wartość podwójną i pasek po cyfrach z dokładnością do drugiego miejsca po przecinku, a nie zaokrąglić liczby, możesz po prostu odjąć 0,005 od numeru, aby runda zadziałała. Na przykład.

double x = 98.7654321; 
Console.WriteLine(x); 
double y = Math.Round(x - 0.005, 2); 
Console.WriteLine(y); 

Produkuje ten ...

98.7654321 
98.76 
+0

jeśli x = 12.125 to dostanie 12,13, co wydaje się nie być tym, czego chce. –

+0

edytowane w celu dodania opcji zaokrąglania –

0

Jeśli szukasz mieć dwa punkty po przecinku bez zaokrągleń liczby dodaje powinien działać

string doubleString = doublevalue.ToString("0.0000"); //To ensure we have a sufficiently lengthed string to avoid index issues 
Console.Writeline(doubleString 
      .Substring(0, (doubleString.IndexOf(".") +1) +2)); 

Drugim parametrem podciągu jest licznik, a IndexOf powraca do zera indeks, więc musimy dodać do niego jedną, zanim dodamy 2 wartości dziesiętne.

Ta odpowiedź jest przy założeniu, że wartość ta powinna być niezaokrągloną

2

Jestem pewien, że istnieje coś więcej .netty tam, ale dlaczego nie po prostu: -

double truncVal = Math.Truncate(val * 100)/100; 
double remainder = val-truncVal; 
+1

Typ "dziesiętny" może oferować mniejsze ryzyko błędu zaokrąglania zmiennoprzecinkowego. –

0

Jak o:

double num = 12.12890; 
double truncatedNum = ((int)(num * 100))/100.00; 
+0

Zrobiłem benchmarking i ta metoda jest 2x szybsza niż oryginalna Math.Truncate. Dzięki za udostępnienie – mca

2

To może działać (chociaż nie testowane):

public double RoundDown(this double value, int digits) 
{ 
    int factor = Math.Pow(10,digits); 

    return Math.Truncate(value * factor)/factor; 
} 

Wtedy po prostu używać go tak:

double rounded = number.RoundDown(2); 
4
double original = 12.123456789; 

double truncated = Truncate(original, 2); 

Console.WriteLine(truncated.ToString()); 
// or 
// Console.WriteLine(truncated.ToString("0.00")); 
// or 
// Console.WriteLine(Truncate(original, 2).ToString("0.00")); 


public static double Truncate(double value, int precision) 
{ 
    return Math.Truncate(value * Math.Pow(10, precision))/Math.Pow(10, precision); 
} 
+1

Byłoby lepiej, gdybyś również wyjaśnił kod. –

0

Do stosowania vb.net tego rozszerzenia:

Imports System.Runtime.CompilerServices 

Module DoubleExtensions 

    <Extension()> 
    Public Function Truncate(dValue As Double, digits As Integer) 

     Dim factor As Integer 
     factor = Math.Pow(10, digits) 

     Return Math.Truncate(dValue * factor)/factor 

    End Function 
End Module 
Powiązane problemy