2013-03-20 14 views
6

Niedawno natknąłem co wydaje puzzle moją logikę matematyki w kawałku koduif ((123/1000)> 0) zwraca false

if((123/1000) > 0) 

z jakiegoś powodu, C# jest twierdząc, że jest to fałszywy ale jeśli logicznie myślimy, to 0.123 to większy niż 0.

Czy istnieje jakiś powód, dla którego twierdzenie, że 0.123 jest mniejsze niż 0?

Czytałem, że nie będzie to kwestia porównania z podwójnie czyli podstawa 2 i byłoby lepiej użyć po przecinku, która jest podstawa 10.

Może ktoś mnie oświeci?

+5

int/int jest zawsze int ... Hej jest to dobry pomysł na piosenkę ... – ppeterka

+0

co jeśli ((123.0/1000.0)> 0.0) dajesz? – Dutts

+0

alteast jeden z operandów powinien być liczbą zmiennoprzecinkową, można podać 'if ((123d/1000)> 0)' – Habib

Odpowiedz

15

Twój błędem jest to, że myślisz, że wynik jest 0.123 natomiast jest 0 zamiast.

C# (i wiele innych języków takich jak C) określenia, że ​​operacje związane z dwóch integralnych liczby powrotu zawsze liczbą całkowitą, tak 1 + 1 powróci 2, nie 2.0 i 3/2 powróci 1 nie 1.5. Część ułamkowa w tym przypadku jest po prostu odrzucana, więc zawsze zaokrągla się do zera (to znaczy, że dla pozytywnych wyników ją zaokrągla, dla ujemnych ją zaokrągla).

Chociaż jest to trochę sprzeczne z intuicją, główną przyczyną jest prostota języka/kompilatora, szybkość wykonywania (ponieważ nie trzeba wymyślać, jaki typ ma wynik), możliwość korzystania z operatorów takich jak /=, które nie zadziałałby, gdyby wynik był innego typu) i historycznej spuścizny i bezwładności.

Do tego trzeba wykonać co najmniej jeden z twoich argumentów liczbę zmiennoprzecinkową rozwiązać (drugi będzie naśladownictwa automatycznie, podobnie jak wynik):

// either 
if (123.0/1000 > 0) 
// or 
if (123/1000.0 > 0) 
// or 
if (123.0/1000.0 > 0) 

Jeśli masz zmienne zamiast tego może potrzebować typecast (jak nie można po prostu dołączyć .0 :-)):

if ((double)a/b > 0) 

i zwykle rada odnosi się również tutaj: Przy programowaniu rzadko zaufać swojej intuicji, ponieważ komputery są dziwne maszyny i języki programowania czasami nawet ul leśniczy. Drukowanie wyniku gdzieś lub przypisanie go do zmiennej i sprawdzanie w debugerze pokazałoby, że twoje oczekiwania były wyłączone :-)

+0

Wybieram twoje jako odpowiedź, ponieważ jest najbardziej wszechstronne. Dziękuję za wyjaśnienie! –

0

Użyj tego:

if((123.0/1000) > 0) 

Próbujesz podzielić int przez int. Więc otrzymujesz podział na liczby całkowite. Ale musisz użyć podwójnego.

A jeśli chcesz się podzielić Int zmienne i uzyskać podwójne wykorzystanie tego:

double doubleNum = (double)intNum1/(double)intNum2; 
9

123 i 1000 są liczbami całkowitymi, a wynik jest mniejszy niż 1, więc jest to w zaokrągleniu do 0. Użyj tego:

123.0/1000.0 > 0.0 

Będzie używać podwójnej precyzji, tzn. Możesz mieć ułamek!

4

Od 123 i 1000Int32 wynikają musi być Int32. Ale ponieważ wynik jest mniejszy niż 1, jest automatycznie zaokrąglany do 0.

Chcesz, aby przynajmniej te liczby były liczbami zmiennoprzecinkowymi.

if(123.0/1000.0 > 0.0) 
{ 
    if((123.0/1000) > 0) 
    { 
     if((123/1000.0) > 0) 
     { 
      Console.WriteLine("True"); // Prints True 
     } 
    } 
} 

Oto DEMO.

Sprawdź to pytanie również Possible Loss of Fraction

+0

Vomit. Narażasz kogoś nowego na kodowanie poczwórnych pojedynczych linii 'if's. Wymioty i brak dalszych komentarzy –

+1

@KierenJohnstone Napisałem to jako przykład z moim wyjaśnieniem. Ale skąd wiadomo, że jest nowy w kodowaniu? To tylko założenie. I myślę, że używanie zagnieżdżonego 'if's' jest nie tylko dla doświadczonych programistów. W leasingu i tak nie zasługuje na to. –

+1

Jest to pytanie o niskiej jakości z literówką, kodem niskiej jakości i komentarzami o niskiej jakości. Nie mogę polecić tej odpowiedzi, widzę tylko wady. W związku z powyższym, z dołu: –

-1

Podczas wykonywania podziału tylko z wartościami całkowitymi, wynik będzie również liczbą całkowitą.

Jeśli prawidłowo przywołam część po przecinku, zostanie ona usunięta.

więc kod zostanie skompilowany do czegoś podobnego.

a = int(123/1000) <--- evaluates to 0. 
if (a > 0) ....  <--- false 

Rozwiązania jak za @algreat odpowiedzi jest zmuszenie jeden z argumentów za double (dodając .0 Zmusi to wynik będzie pływak ., jak również

+1

-1: 'floor' jest funkcją języka C, a dodanie' .0' nie powoduje, że jest zmiennoprzecinkowe, czyni to 'podwójnym' –

1

int/int jest int - co oznacza, że ​​123/1000 jest 0 i nie 0.123 jak można się spodziewać -

si nce 0 nie jest większe niż 0, wyrażenie zwraca wartość false!

Rozwiązaniem jest, aby jedną z liczb całkowitych jako podwójne -

if(123.0/1000 > 0) <- true 
if(123/1000.0 > 0) <- true 
if(123.0/1000.0 > 0) <- true 
2

Mimo to zostało odebrane, nikt nie dał dobry punkt widzenia tego problemu, więc chciałem to zrobić bardziej jasne:

Jeśli jesteś dividing lub multiplyingint i float dostaniesz wyniki tak:

int/int => int 
float/int => float 
int/float => float 

więc jeśli podzielenie:

123/1000 => 0 (as there is no int number 0.123, it will then set to 0) 
123.0/1000 => 0.123 (this dividing is basically saying that I need a float result of dividing) 
123/1000.0 => 0.123 (this says the same as previous) 

więc zasada jest w zasadzie - jeśli używasz typ, który jest na poziomie „górny”, że jeden jest używany, a następnie obliczenie będzie tłumaczony do " rodzic "typ. Ale nie można tego ogólnie powiedzieć, tak jakby używany był typ zmiennoprzecinkowy, zawsze będzie przekazywany do liczby zmiennoprzecinkowej.Oto więcej przykładów:

long/int => long 
double/float => double 
double/int => double 

A jeśli chcesz mieć odpowiedź do twojego pytania, odpowiedź byłoby umieścić:

if(((float)123/1000) > 0) 

lub

if(((double)123/1000) > 0) 

więc obliczyłby zawsze liczbę zmiennoprzecinkową (numer 0.123)