Czy ktoś wie, dlaczego dzielenie liczb całkowitych w C # zwraca liczbę całkowitą, a nie liczbę zmiennoprzecinkową? Jaka jest idea? (Czy to tylko dziedzictwo C / C ++?)
W C #:
float x = 13 / 4;
//== operator is overridden here to use epsilon compare
if (x == 3.0)
print 'Hello world';
Wynik tego kodu byłby:
'Hello world'
Ściśle mówiąc, nie ma czegoś takiego jak dzielenie liczb całkowitych (dzielenie z definicji jest operacją, która daje liczbę wymierną, liczby całkowite to bardzo mały podzbiór).
integer
podział, a niefloating point
podział.Odpowiedzi:
Podczas gdy nowi programiści często popełniają ten błąd, wykonując dzielenie liczb całkowitych, gdy w rzeczywistości zamierzali używać dzielenia zmiennoprzecinkowego, w praktyce dzielenie liczb całkowitych jest bardzo powszechną operacją. Jeśli zakładasz, że ludzie rzadko go używają i że za każdym razem, gdy robisz dzielenie, zawsze musisz pamiętać o rzucaniu na zmienne punkty, to się mylisz.
Po pierwsze, dzielenie liczb całkowitych jest nieco szybsze, więc jeśli potrzebujesz tylko wyniku w postaci liczby całkowitej, chciałbyś użyć bardziej wydajnego algorytmu.
Po drugie, istnieje wiele algorytmów wykorzystujących dzielenie całkowitoliczbowe i jeśli wynikiem dzielenia byłaby zawsze liczba zmiennoprzecinkowa, musiałbyś za każdym razem zaokrąglić wynik. Jednym z przykładów z czubka mojej głowy jest zmiana podstawy liczby. Obliczanie każdej cyfry polega na dzieleniu liczby całkowitej wraz z resztą, a nie na dzieleniu liczby zmiennoprzecinkowej.
Z tych (i innych powiązanych) powodów dzielenie liczb całkowitych daje w wyniku liczbę całkowitą. Jeśli chcesz uzyskać dzielenie zmiennoprzecinkowe dwóch liczb całkowitych, musisz po prostu pamiętać o rzutowaniu jednej na
double
/float
/decimal
.źródło
/
operator będzie wykonywał dzielenie liczb całkowitych, czy zmiennoprzecinkowych (chyba że używasz dynamicznego). Jeśli trudno ci to rozgryźć, ponieważ robisz tak dużo w tym jednym wierszu, sugerowałbym podzielenie tego wiersza na kilka wierszy, aby łatwiej było ustalić, czy operandy są liczbami całkowitymi, czy zmiennoprzecinkowymi. Przyszli czytelnicy Twojego kodu prawdopodobnie to docenią.int/int
operator był po prostu nielegalny [z diagnostyką określającą, że kod musi rzutować operand lub używać inny operator, w zależności od tego, jakie zachowanie było pożądane]. Gdyby istniała inna dobra sekwencja znaczników do dzielenia liczb całkowitych, można by zrezygnować z używania/
do tego celu, ale nie wiem, co byłoby praktyczne.Zobacz specyfikację języka C # . Istnieją trzy typy operatorów dzielenia
W Twoim przypadku mamy podział typu Integer z następującymi zasadami:
Myślę, że powodem, dla którego C # używa tego typu dzielenia liczb całkowitych (niektóre języki zwracają wynik zmiennoprzecinkowy) jest sprzęt - dzielenie liczb całkowitych jest szybsze i prostsze.
źródło
Każdy typ danych może przeciążać każdego operatora. Jeśli zarówno licznik, jak i mianownik są liczbami całkowitymi, typ liczby całkowitej wykona operację dzielenia i zwróci typ całkowity. Jeśli chcesz podzielić zmiennoprzecinkowe, musisz rzutować jedną lub więcej liczb na typy zmiennoprzecinkowe przed ich podzieleniem. Na przykład:
int x = 13; int y = 4; float x = (float)y / (float)z;
lub, jeśli używasz literałów:
float x = 13f / 4f;
Pamiętaj, że zmiennoprzecinkowe nie są dokładne. Jeśli zależy Ci na dokładności, użyj zamiast tego czegoś takiego jak typ dziesiętny.
źródło
Ponieważ nie używasz żadnego sufiksu, literały
13
i4
są interpretowane jako liczby całkowite:Tak więc, ponieważ deklarujesz
13
jako liczbę całkowitą, zostanie wykonany podział całkowity:I tak następuje zaokrąglenie w dół:
Jeśli wykonasz następujące czynności:
int x = 13f / 4f;
Otrzymasz błąd kompilatora, ponieważ dzielenie zmiennoprzecinkowe (
/
operator13f
) powoduje powstanie liczby zmiennoprzecinkowej, której nie można niejawnie rzutować na wartość int.Jeśli chcesz, aby dzielenie było dzieleniem zmiennoprzecinkowym, musisz sprawić, że wynik będzie zmiennoprzecinkowy:
float x = 13 / 4;
Zauważ, że nadal będziesz dzielił liczby całkowite, które niejawnie zostaną rzutowane na zmiennoprzecinkowe: wynik będzie
3.0
. Aby jawnie zadeklarować operandy jako zmiennoprzecinkowe, używającf
sufiksu (13f
,4f
).źródło
1.0
.To tylko podstawowa operacja .
Pamiętaj, kiedy nauczyłeś się dzielić. Na początku rozwiązaliśmy
9/6 = 1 with remainder 3
.9 / 6 == 1 //true 9 % 6 == 3 // true
/ -Operator w połączeniu z% -operator są używane do pobierania tych wartości.
źródło
Może się przydać:
double a = 5.0/2.0; Console.WriteLine (a); // 2.5 double b = 5/2; Console.WriteLine (b); // 2 int c = 5/2; Console.WriteLine (c); // 2 double d = 5f/2f; Console.WriteLine (d); // 2.5
źródło
2.5
, nie2
.Wynik zawsze będzie typu, który ma większy zakres licznika i mianownika. Wyjątki są bajtowe i krótkie, które dają int (Int32).
var a = (byte)5 / (byte)2; // 2 (Int32) var b = (short)5 / (byte)2; // 2 (Int32) var c = 5 / 2; // 2 (Int32) var d = 5 / 2U; // 2 (UInt32) var e = 5L / 2U; // 2 (Int64) var f = 5L / 2UL; // 2 (UInt64) var g = 5F / 2UL; // 2.5 (Single/float) var h = 5F / 2D; // 2.5 (Double) var i = 5.0 / 2F; // 2.5 (Double) var j = 5M / 2; // 2.5 (Decimal) var k = 5M / 2F; // Not allowed
Nie ma niejawnej konwersji między typami zmiennoprzecinkowymi a typami dziesiętnymi, więc dzielenie między nimi jest niedozwolone. Musisz jawnie rzutować i zdecydować, który z nich chcesz (Decimal ma większą precyzję i mniejszy zakres w porównaniu do typów zmiennoprzecinkowych).
źródło