Floor, ceil i reszta

Uwaga! Informacje na tej stronie mają ponad 5 lat. Nadal je udostępniam, ale prawdopodobnie nie odzwierciedlają one mojej aktualnej wiedzy ani przekonań.

# Floor, ceil i reszta

Fri
09
May 2008

Mieliśmy właśnie przed chwilą na IRC-u dyskusję o zasadach, według jakich działa zaokrąglanie/obcinanie liczb zmiennoprzecinkowych przez funkcje floor, ceil i rzutowanie na int. Przypomniałem sobie, że to temat, z którym nieraz się już spotkałem i pomyślałem, że warto to usystematyzować:

x          -2.9  -2.2   2.2   2.9
---------------------------------
(int)x     -2    -2     2     2
floor(x)   -3.0  -3.0   2.0   2.0
ceil(x)    -2.0  -2.0   3.0   3.0
round(x)   -3.0  -2.0   2.0   3.0

Problem w tym, że funkcji zaokrąglającej round w C++ nie ma, trzeba ją sobie napisać. Podobnie brakuje funkcji zostawiającej samą część ułamkową 0..1, a jest ona bardzo potrzebna np. do robienia funkcji okresowych i występuje np. w języku HLSL jako frac.

inline int round(float x) {
  return (int)(x+0.5f);
}
inline float frac(float x) {
  return x - (float)(int)(x);
}

Nie jestem tylko pewny, czy rzutowanie na int faktycznie zawsze obcina część ułamkową. Na moim Visual C++, Windows XP i procesorze Intel Core2Duo 32bit tak jest, ale nie zaglądałem do standardu C++, więc nie wiem czy tak samo jest wszędzie. Wkrótce jakiś językoznawca powinien wyjaśnić tą kwestię w tym wątku forum. Gdyby się jednak okazało, że nie można polegać na tym rzutowaniu, funkcję obcinającą część ułamkową można sobie napisać samemu:

inline float trunc(float x) {
  return (x < 0.0f) ? ceilf(x) : floorf(x);
}

Takich niby prostych (prostych dla tego co już je zna) sztuczek matematycznych jest bardzo dużo. Przydałoby się je kiedyś porządnie spisać :) Na przykład ta nasza dyskusja IRC-owa zaczęła się od pytania, jak obciąć liczbę do 2 miejsc po przecinku. Rozwiązaniem jest:

y = (float)(int)(x * 100.0f) / 100.0f;

Comments | #c++ #math #algorithms Share

Comments

STAT NO AD
[Stat] [STAT NO AD] [Download] [Dropbox] [pub] [Mirror] [Privacy policy]
Copyright © 2004-2019