2011-01-31 25 views
5

Wiem, że przy dzieleniu liczb całkowitych domyślnym sposobem działania jest odrzucenie części ułamkowej. NpDzielenie liczb całkowitych

int i, n, calls = 0; 
n = 1; 
n /= 3; 
printf("N = %i\n", n); 
for (i = 1; i > 0; i /= 3) { 
    calls++; 
} 
printf("Calls = %i\n", calls); 

Powyższy kod odbitek:

N = 0 
Calls = 1 

mógłbyś wyjaśnić to zachowanie?

+3

ja nie rozumiem, czy nie odpowiedzieć na to pytanie w pierwszym zdaniu? –

+0

Czy mógłbyś * wyjaśnić, co uważasz za niezwykłe w tym zachowaniu? –

+0

Myślę, że moja odpowiedź jest wystarczająca. –

Odpowiedz

14

1 podzielone przez 3 = .3333 (powtórzenie oczywiście), matematycznie. Możesz myśleć o komputerze jako obcinającym .3333, ponieważ robi on całkowitą arytmetykę (0 pozostałość 1).

Pętla for wykonuje się, ponieważ i = 1 i 1 > 0. Po wykonaniu ciała pętli, dzielisz i przez trzy, a i staje się 0, co nie jest większe niż 0.

+3

@mizo: Nie, warunek jest sprawdzany, zanim ciało zostanie wprowadzone po raz pierwszy. Jeśli ustawisz 'i = -1;' w pierwszej części instrukcji 'for', to treść pętli zostanie całkowicie pominięta. –

+1

+1 dla geeky WoW reference. Przypuszczam, że mogłem dać +1 za poprawność, ale, do cholery. 6 innych już to zrobiło. :) –

+0

@ James, masz rację. Usunięto niepoprawny komentarz :) – mizo

1

Ponieważ wykonuje pętlę raz.

Przyrost pętli for jest wykonywany po ciała pętli, a na wejście pętli i > 0 jest prawdziwe, 1 > 0 na podział występuje obok pętli, a następnie przeprowadzony test fałszywy i wyjście pętli.

3

przepisać jako while i staje się oczywiste.

i = 1; 
while (i > 0) 
{ 
    calls++;   
    i /= 3; //This becomes .3333, which truncates to zero 
} 
-2

To wszystko jest bardzo proste.

int i, n, calls = 0; // Set calls to 0 
n = 1;    // n is now 1 
n /= 3;    // n /= 3 = 1/3 = 0 
printf("N = %i\n", n); 
for (i = 1; i > 0; i /= 3) { // 1/3 = 0 
    calls++;     // runs once 
}        
printf("Calls = %i\n", calls); 

Mam nadzieję, że to pomoże.

+0

@James masz rację, zredagowałem moją odpowiedź. –

+0

Nie jestem pewien, czy rozumiem Twój komentarz dotyczący przyrostu przed i po. Skoro nie przechwytuje on zwrotu operacji przyrostowej, jaki problem polega na zmianie tego ustawienia na pre-inkrementację? –

+0

Cała część przyrostowa przed/po nie ma żadnego znaczenia dla zachowania. Ciało pętli jest wykonywane raz. Tylko to się liczy. –

1

Gdzie jest problem? Pierwszy wiersz wyjścia jest natychmiastowy: 1/3 = 0,33333 ..., usunięcie części ułamkowej to 0.

Na drugim wierszu należy pamiętać, że cykl for jest tłumaczona na coś takiego:

i=1; 
while(i>0) 
{ 
    calls++; 
    i/=3; 
} 

Na początku i ma wartość 1; pierwsza iteracja while jest wykonywana, ponieważ i, będąc 1, jest większa niż 0. calls jest 0 i jest zwiększana o 1, a więc dostaje się do 1. i jest dzielona przez 3, więc dostaje się do 0 (ponieważ część ułamkowa jest nie obliczane w całkowitym podziałem). Sprawdzanie stanu while jest wykonywane ponownie, ale teraz i ma wartość 0, więc cykl nie jest powtarzany. calls pozostaje na 1, a ta wartość jest drukowana na ekranie.

0

n jest int podział powróci liczbą całkowitą, a nie podwójne lub unosić

0

Ponieważ w całkowitej arytmetycznych, w odpowiedzi na 1 podzielone przez 3 jest 0 z resztą 1. Po podzieleniu dwie liczby całkowite, otrzymujesz całkowitą arytmetykę. Jeśli potrzebujesz arytmetyki zmiennoprzecinkowej, potrzebujesz co najmniej jednego argumentu jako wartości zmiennoprzecinkowej.

Powiązane problemy