2010-07-21 21 views
79

Czy jest jakaś różnica między nimi:Obsada int vs piętrze

float foo1 = (int)(bar/3.0); 
float foo2 = floor(bar/3.0); 

Jak rozumiem oba przypadki mają ten sam rezultat. Czy jest jakaś różnica w skompilowanym kodzie?

+0

nieco lepiej z 'podłogą', ale uważaj, że jest to dla' double' nie dla 'float'. C99 ma również 'floorf' dla' float'. –

+2

Więc mają ten sam wynik, o ile pasek jest dodatni – Zac

Odpowiedz

135

odlewnicze do int będzie obciąć do zera. floor() spowoduje obcięcie w kierunku ujemnego nieskończoności. Da ci to różne wartości, jeśli bar będzie ujemny.

+14

Myślę, że trafiłeś w sedno tutaj. Inną różnicą, jeśli 'floor()' jest intencją, jest jeśli wartość 'bar' jest zbyt duża, aby zmieścić się w' int'. –

+0

Czy masz jakieś źródło tego stwierdzenia? – HelloGoodbye

4

EDYCJA: Ponieważ pytanie mogło zostać zmodyfikowane z powodu pomyłki między fabs() i floor().

Podane oryginalne przykładowe pytanie linie:

1. float foo = (int)(bar/3.0); 

2. float foo = fabs(bar/3.0); 

Różnica polega na tym, że jeśli pasek jest ujemny wynik będzie ujemny z pierwszym ale pozytywny z drugim. Pierwsza zostanie obcięta do liczby całkowitej, a druga zwróci pełną wartość dziesiętną, w tym część ułamkową.

8

Jak myślisz, dlaczego będą one miały taki sam rezultat?

float foo = (int)(bar/3.0) //will create an integer then assign it to a float 

float foo = fabs(bar/3.0) //will do the absolute value of a float division 

bar = 1.0 

foo1 = 0; 
foo2 = 0.33333... 
3

Tak. fabs zwraca bezwzględną wartość swojego argumentu, a rzutowanie na int powoduje obcięcie podziału (w dół do najbliższej int), więc wyniki prawie zawsze będą różne.

0

(int) x jest prośba, aby utrzymać część całkowitą x (nie ma tu zaokrągleń)

fabs(x) = | x | tak, że jest to >= 0;

Np .: (int) -3.5 zwraca -3; fabs(-3.5) zwraca 3.5;

Ogólnie rzecz biorąc, fabs (x) >= x dla wszystkich x;

x >= (int) x jeśli x >= 0

x < (int) x jeśli x < 0

+0

Twoje ostatnie zdanie jest błędne; rozważ swój przykład -3. –

+0

x = -3 fabs (-3) = 3 (int) -3 = -3; Myślę, że ostatnie nierówności utrzymują się. Czy możesz dokładniej wyjaśnić, dlaczego jest nie tak? –

+0

Przepraszam, miałem na myśli -3,5, przykład, który podałeś. -3> -3.5 –

21

Jak już wcześniej wspomniano, dla liczb dodatnich są one takie same, ale różnią się liczbami ujemnymi. Zasadą jest, że int zaokrągla się w kierunku 0, podczas gdy podłoga zaokrągla się w kierunku ujemnej nieskończoności.

floor(4.5) = (int)4.5 = 4 
floor(-4.5) = -5 
(int)(-4.5) = -4 

Jest to również różnica w czasie realizacji. W moim systemie czas był taki, że rzut jest co najmniej 3 razy szybszy niż podłoga.

Mam kod, który wymaga operacji piętra o ograniczonym zakresie wartości, w tym liczb ujemnych. I to musi być bardzo wydajny, więc używamy następującą funkcję do niego:

int int_floor(double x) 
{ 
    return (int)(x+100000) - 100000; 
} 

Oczywiście będzie to fail dla bardzo dużych wartości x (wpadniemy w niektórych kwestiach przelewowe) oraz dla wartości ujemnych poniżej - 100000 itd. Ale zmusiłem go do tego, aby był co najmniej 3 razy szybszy od podłogi, co było bardzo ważne dla naszej aplikacji. Weź to z przymrużeniem oka, przetestuj na swoim systemie itp.ale warto wziąć pod uwagę IMHO.

2

Istnieją dwa główne różnice:

  1. jak inni wykazali, odlewanie do całkowitej będzie obciąć do zera, podczas gdy floor() zawsze obciąć do minus nieskończoności; to jest inne zachowanie dla negatywnego argumentu.

  2. nikt (jeszcze) wydaje się, że wskazał inną różnicę - jeśli argument jest większy lub równy MAX_INT+1 (lub mniej niż -MAX_INT-1), a następnie rzucając na int spowoduje górnym większości bitów przed upadkiem (Prawdopodobnie C) lub niezdefiniowane zachowanie (C++ i ewentualnie C). EG jeśli twój int ma 32 bity, będziesz miał tylko bit znaku i 31 bitów danych. Używanie tego z dużym rozmiarem spowoduje uzyskanie niezamierzonych rezultatów.

+0

2.a. Dokładny warunek konwersji na przepełnienie 'int' jest taki, że argument jest większy lub równy' INT_MAX' + 1. Symetrycznie warunkiem niedomiaru jest to, że argument jest mniejszy lub równy "INT_MIN"-1. –

+1

2.b. Przepełnienie w konwersji z liczby zmiennoprzecinkowej na całkowitą jest niezdefiniowanym zachowaniem w C++. Nie "powoduje to upuszczenia najwyżej położonych bitów". Zobacz (chociaż jest napisane dla C): http://blog.frama-c.com/index.php?post/2013/10/09/Overflow-float-integer –

+0

@PascalCuoq naprawiony – abligh