2013-07-14 12 views
6

Potrzebuję obcinać liczbę do 2 miejsc po przecinku, co w zasadzie oznacza odcinanie dodatkowych cyfr.Obcinanie liczby do określonych miejsc dziesiętnych

Np

2.919  ->  2.91 

2.91111 ->  2.91 

Dlaczego? Właśnie to robi serwer SQL, gdy zapisuje się określoną liczbę precyzji . Np. Jeśli kolumna jest dziesiętna (8,2), a Ty spróbujesz wpisać wstawić/zaktualizować liczbę 9.1234, 3 i 4 zostaną odcięte.

Potrzebuję zrobić dokładnie to samo w kodzie C#.

Jedyne możliwe sposoby, że mogę myśleć robi to albo:

  1. Używanie stringformatter do „print” go tylko dwóch miejsc po przecinku, a następnie przekształcenie go do postaci dziesiętnej, np :

    decimal tooManyDigits = 2.1345 
    
    decimal ShorterDigits = Convert.ToDecimal(tooManyDigits.ToString("0.##")); 
    
    // ShorterDigits is now 2.13 
    

    nie jestem zadowolony z tego, ponieważ wiąże się to ciąg znaków, a potem inny napis na dziesiętny konwersji, który wydaje się nieco szalony.

  2. Stosując Math.Truncate (który przyjmuje tylko liczbą całkowitą) tak, że można pomnożyć przez 100 obcina się, a następnie podzielenie przez 100. np:

    decimal tooLongDecimal = 2.1235; 
    
    tooLongDecimal = Math.Truncate(tooLongDecimal * 100)/100; 
    

    nie jestem również zadowolony to dlatego, że jeśli zbyt długoDługi jest 0, , otrzymam dzielenie przez błąd 0.

Z pewnością istnieje lepszy i łatwiejszy sposób! Jakieś sugestie?

+2

'0/100' nie jest dzielenie przez 0 błędów. To jest '0', czego można się spodziewać. – xbonez

+0

(0 * 100)/100 = 0 –

+0

@sehe truncate! = Runda –

Odpowiedz

5

Sam odpowiedziałeś na to pytanie; Wygląda na to, że źle zrozumiałeś podział na zero. Poprawny sposób to zrobić, aby pomnożyć, obciąć, a następnie podzielić w następujący sposób:

decimal TruncateTo100ths(decimal d) 
{ 
    return Math.Truncate(d* 100)/100; 
} 

TruncateTo100ths(0m);  // 0 
TruncateTo100ths(2.919m); // 2.91 
TruncateTo100ths(2.91111m); // 2.91 
TruncateTo100ths(2.1345m); // 2.13 

Nie ma dzielenie przez zero, tu, tam jest tylko podział przez 100, który jest całkowicie bezpieczne.

+0

Mamo, którą mnie pokonałeś :) właśnie pisałem ten sam przykład matematyczny. Lol +1. – terrybozzio

0

Korzystanie decimal.ToString('0.##')również nakłada zaokrągleń:

1.119M.ToString("0.##") // -> 1.12 

(. Tak, prawdopodobnie powinien być komentarz, ale trudno dobrze sformatować jako takie)

3

Uprzednio Oferowane rozwiązania matematyczne są podatne na przepełnienie w dużych ilościach i/lub dużej liczby miejsc po przecinku.Rozważmy zamiast następujące rozszerzenia:

[System.Runtime.CompilerServices.Extension()] 
public static decimal TruncateDecimal(decimal d, int decimals) 
{ 
    if (decimals < 0) 
     throw new ArgumentOutOfRangeException("decimals", "Value must be in range 0-28."); 
    else if (decimals > 28) 
     throw new ArgumentOutOfRangeException("decimals", "Value must be in range 0-28."); 
    else if (decimals = 0) 
     return Math.Truncate(d); 
    else { 
     decimal integerPart = Math.Truncate(d); 
     decimal scalingFactor = d - integerPart; 
     decimal multiplier = Math.Pow(10, decimals); 

     scalingFactor = Math.Truncate(scalingFactor * multiplier)/multiplier; 

     return integerPart + scalingFactor; 
    } 
} 

Zastosowanie:

decimal value = 18446744073709551615.262626263m; 
value = value.TruncateDecimal(6); 
Powiązane problemy