2

What is the correct alternative to the C99 lrint function in windows?

#define lrint(x) (floor(x+(x>0) ? 0.5 : -0.5)) 

/* and if fesetround(0) behavior is required*/

#define lrint(x) ((int)(x))  

is that correct?

Carlos Barbosa
  • 1,422
  • 2
  • 23
  • 42
  • 1
    @Insilico The code he provided originally does work if `fesetround(0)` was called before `lrint`. Now it simply produces 0 if `x>=0`, otherwise -1. – Sam Harwell Mar 10 '13 at 06:23
  • I misread the documentation - I should have written `fesetround(FE_TOWARDZERO)`, not `fesetround(0)`. – Sam Harwell Mar 10 '13 at 06:32
  • Pro tip: In C++, if your proposed solution starts with `#define`, you're almost surely doing it wrong. Whenever possible, use an inline function instead. – Sam Harwell Mar 10 '13 at 06:35

2 Answers2

3

There is no [simple] single definition of lrint which performs the behavior defined by the C99 standard. This is due to the fact that the behavior of lrint is controlled by separate calls to fesetround. Instead, you should use separate rounding functions with guaranteed semantics for the desired behavior of your application.

Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
0
floor(x+(x>0) ? 0.5 : -0.5)

will correctly round only positive numbers, but not negative because floor() rounds towards negative infinity, meaning that floor(-7.1)=-8 , and the quoted piece of code doesn't fix that: floor(-7.1-0.5)=-8 still, while correct rounding to the nearest integer must result in -7. The following piece of code does correct rounding:

return int(x + ((x >= 0.0) ? 0.5 : -0.5));

Alternatively,

return ((x >= 0.0) ? floor(x+0.5) : ceil(x-0.5));
Serge Rogatch
  • 13,865
  • 7
  • 86
  • 158