2012-05-22 10 views
15

Próbuję wyodrębnić integralne i ułamkowe części od wartości dziesiętnych (obie części powinny być liczbami całkowitymi):Podział zmienna dziesiętny do integralnych i ułamkowych częściach

decimal decimalValue = 12.34m; 
int integral = (int) decimal.Truncate(decimalValue); 
int fraction = (int) ((decimalValue - decimal.Truncate(decimalValue)) * 100); 

(dla mojego celu, zmienne dziesiętnych będzie zawierać do 2 miejsc po przecinku)

Czy istnieją lepsze sposoby osiągnięcia tego?

+0

Lepszym rozwiązaniem może być użycie przecinku w ogóle, ale użyć 'int' /' long' reprezentujący „swoją wartość pomnożone przez 100” . – Rawling

+0

Uważaj na nietypowe wartości. Maksymalna wartość dziesiętna wynosi ~ 7.9e28. Maksymalna wartość dla int wynosi ~ 2e9 (znacznie mniejsza). Nawet długo trwa ~ 9e18. Więc jeśli wiesz, że wartość zawsze będzie> = 0, możesz użyć ulong, który ciągnie się aż do ~ 18e18, dając nieco więcej swobody. – Davio

+0

Następująca odpowiedź na podobne pytanie może odpowiadać tym potrzebom części ułamkowej: http://stackoverflow.com/a/13038524/1178314 –

Odpowiedz

1

Jak o:

int fraction = (int) ((decimalValue - integral) * 100); 
+0

Z pewnością nie będzie działać dla liczb ujemnych. – SOReader

+1

Co to jest "integralna"? –

-1

jak o użyciu funkcji toString a następnie podzielone na miejsca po przecinku, tj:

[edytuj] szybkie trochę klasy/metody badania:

public class Test 
{ 
    public struct FractionSplit 
    { 
     public int BeforeDecimal; 
     public int AfterDecimal; 
    } 

    public FractionSplit SplitDecimal(decimal decimalValue, 
             int decimalPrecision = 2) 
    { 
     // now do the split - the apres decimal precision defined by 
     // the format function which defaults to 2 places i.e. "0.00" 
     string splitValue = decimalValue.ToString(string.Format("0.{0}", 
      new String('0', decimalPrecision)), CultureInfo.InvariantCulture); 
     string[] splitParts = splitValue.Split('.'); 

     // now factor out derived splits as ints into struct 
     var fractionSplit = new FractionSplit 
     { 
      BeforeDecimal = int.Parse(splitParts[0]), 
      AfterDecimal = int.Parse(splitParts[1]) 
     }; 

     return fractionSplit; 
    } 
} 

użycie:

Test test = new Test(); 
var result = test.SplitDecimal(12.1m); 

zgodnie z komentarzem Dana, to faktycznie wywnioskuje, że 12.1 zwraca 12 i 10 jako wynikowe liczby całkowite. Czy to jest poprawne?? - kto wie, ale na razie omija tę sprawę. Wynika to z części ToString ("0. {0}"), która domyślnie dodaje "0" na końcu dowolnej części dziesiętnej, która ma tylko jedną cyfrę.

+0

będzie 0,1 dawać taki sam wynik, jak 0,10 lub 0,01? – Dan

+0

ashh-good point !! nie jest tak, że nie jest 10 i 1 pożądany wynik? :) tj. 12.10 dałoby 12 i 10, 12,01 dałoby 12, a 1. czy to nie jest poprawne? –

+0

tak, ale co wtedy dałoby 12,1? Prawdopodobnie 1, gdy pożądany wynik może wynosić 10 ... Nie jestem pewien – Dan

2

Spróbuj definicji matematycznej:

var fraction = (int)(100.0m * (decimalValue - Math.Floor(decimalValue))); 

Mimo że nie jest lepszy w sensie wydajności ale przynajmniej praca dla liczb ujemnych.

+0

Spróbuj użyć tego: var FileMinorPartClient = (int) (100,0m * (clientFileVersion - Math .Floor (clientFileVersion))); Otrzymuję: "Operatora" * "nie można zastosować do argumentów typu" dziesiętny "i" podwójny "" (wersja_klienta to double, a la 1.4) –

+1

@ B.ClayShannon Mówi tak, ponieważ nie można mieszać tych dwóch . Zmień wartość "100.0m" na "100.0" lub upewnij się, że "decimalValue" jest typu "dziesiętnego" – SOReader

7
 decimal fraction = (decimal)2.78; 
     int iPart = (int)fraction; 
     decimal dPart = fraction % 1.0m; 
+0

Bardzo dobre wykorzystanie operatora modułu na dziesiętnym. Nie spodziewałem się, że to zadziała, ale robi się pięknie (i szybko) :) –

3
decimal fraction = doubleNumber - Math.Floor(doubleNumber) 

lub coś podobnego.

1

Na zaciągnięcie frakcję można użyć this solution:

Math.ceil(((f < 1.0) ? f : (f % Math.floor(f))) * 10000)