C/C++ Rounding Cheat Sheet

Tobias Hoffmann

C++ User Treffen Aachen, 2019-07-11

Introduction

  • Aim: Overview/Comparison of rounding functions
  • C/C++ are mostly the same
  • Rounding mode independent: floor*, ceil*, ...
  • Rounding mode dependent: rint*, nearbyint*, ...

Floating Point Environment

  • <fenv.h> / <cfenv>
  • fesetround(FE_TONEAREST), fegetround()
  • fetestexcept(mask), feclearexcept(mask)
  • FE_INVALID, FE_INEXACT, FE_ALL_EXCEPT, ...

Floor

C:
  double floor(double);
  float floorf(float);
  long double floorl(long double);

C++: T={float, double, long double}
  T std::floor(T);

C++11:
  float std::floorf(float);
  long double std::floorl(long double);
  double std::floor(IntegralType); 
  • (long int)floor(x); / floorf / ...
  • Corresponding rounding mode: FE_DOWNWARD

Ceil

C:
  double ceil(double);
  float ceilf(float);
  long double ceill(long double);

C++: T={float, double, long double}
  T std::ceil(T);

C++11:
  float std::ceilf(float);
  long double std::ceill(long double);
  double std::ceil(IntegralType); 
  • (long int)ceil(x); / ...
  • Corresponding rounding mode: FE_UPWARD

Truncate / Round toward zero

C:
  double trunc(double);
  float truncf(float);
  long double truncl(long double);

C++11: T={float, double, long double}
  T std::trunc(T);

  float std::truncf(float);
  long double std::truncl(long double);
  double std::trunc(IntegralType); 
  • (long int)x;
  • Corresponding rounding mode: FE_TOWARDZERO

Round to nearest,
halfway cases away from zero

C:
  double round(double); / float roundf(float); / long double roundl(long double);
  long int lround(double); / lroundf / lroundl
  long long int llround(double); / ...

C++11: T={float, double, long double}
  T std::round(T);
  long std::lround(T); / long long std::llround(T);

  double std::round(IntegralType); / long std::lround(IntegralType) / std::llround 
  • No (standardized) corresponding rounding mode!

Round to nearest,
halfway cases away from zero

- How NOT to do it -


    (long int)(x + 0.5);
  
  • Problem 1: < 0
  • Problem 2: ≥ 223 (float)

Round to nearest,
halfway cases to even

Rounding mode dependent methods (C / C++11) with default mode:
  double rint(double); / rintf / rintl
  T rint(T / IntegralType);

  long lrint(T / IntegralType); / llrint

  T nearbyint(T / IntegralType);

Less commonly available (C only):
  double roundeven(double); / roundevenf / roundevenl 
  • (long int)roundeven(x); / ...
  • Corresponding rounding mode: FE_TOWARDZERO

Round to nearest,
halfway cases upward

  • (long int)floor(x + 0.5); /
    (long int)floorf(x + 0.5f);
  • Has most problems of round-nearest by cast.
  • Better: Use "halfway cases to even"!

Rounding mode dependent

C / C++11:
  rint* - does not raise FE_INEXACT

  nearbyint* - raises FE_INEXACT

  long lrint*, long long llrint*
   - like lround / llround
   - FE_INEXACT is also a domain error (FE_INVALID) 

Other languages

Javascript:
  x|0;   => trunc/cast (limited to 32 bit!)
  Math.round(x);   => Round to nearest, halfway cases upwards
  x.fixed(digits);  - halfway cases are not fully reliable!
  Math.floor(x); / Math.ceil(x); 
PHP:
  $x|0; / intval($x) / (int)$x / (integer)$x;
   => trunc/cast (limited to 32 / 64 bit!)

  round($x,$precision=0,$mode=PHP_ROUND_HALF_UP)
    - $mode=_HALF_UP | _HALF_DOWN | _HALF_EVEN | _HALF_ODD
      since PHP 5.3

  floor($x); / ceil($x); 

Links, Questions?