469,609 Members | 1,640 Online

# lrint and rounding mode

Hello everyone,

I don't understand how the lrint() function works.

long lrint(double x);

The function returns the nearest long integer to x, consistent with the
current rounding mode. It raises an invalid floating-point exception if
the magnitude of the rounded value is too large to represent. And it
raises an inexact floating-point exception if the return value does not
equal x.

The output of the following program does not make sense to me.

#include <cstdio>
#include <cmath>
int main()
{
for (int i=-10; i < 10; ++i)
{
double x = i + 0.5;
printf("lrint(%+f)=%ld\n", x, lrint(x));
}
return 0;
}

\$ g++ -std=c++98 -Wall -Wextra -O2 -march=pentium3 foo.cxx -lm
\$ ./a.out
lrint(-9.500000)=-10
lrint(-8.500000)=-8
lrint(-7.500000)=-8
lrint(-6.500000)=-6
lrint(-5.500000)=-6
lrint(-4.500000)=-4
lrint(-3.500000)=-4
lrint(-2.500000)=-2
lrint(-1.500000)=-2
lrint(-0.500000)=0
lrint(+0.500000)=0
lrint(+1.500000)=2
lrint(+2.500000)=2
lrint(+3.500000)=4
lrint(+4.500000)=4
lrint(+5.500000)=6
lrint(+6.500000)=6
lrint(+7.500000)=8
lrint(+8.500000)=8
lrint(+9.500000)=10

How could 1.5 AND 2.5 be rounded to 2 in the same rounding mode?

Regards.
Sep 18 '07 #1
5 7659
On Tue, 18 Sep 2007 11:20:45 +0200, Spoon <root@localhostwrote:
>Hello everyone,

I don't understand how the lrint() function works.

long lrint(double x);

The function returns the nearest long integer to x, consistent with the
current rounding mode. It raises an invalid floating-point exception if
the magnitude of the rounded value is too large to represent. And it
raises an inexact floating-point exception if the return value does not
equal x.

The output of the following program does not make sense to me.
<...>
>
lrint(+1.500000)=2
lrint(+2.500000)=2

How could 1.5 AND 2.5 be rounded to 2 in the same rounding mode?
I have seen it called the "banker rounding" (in spanish, but I suppose
it should be the same in english.

If the fractional part of the number is less than 0.5, it is rounded
down. If it is more than 0.5, it is rounded up. It it is exactly 0.5,
then if the integral part is odd, it is rounded up, else it is rounded
down.

It makes the rounding smoother, and the probability of accounting and
audit results being the same, higher.

best regards,

Zara
Sep 18 '07 #2
Zara wrote:
Spoon wrote:
>I don't understand how the lrint() function works.

long lrint(double x);

The function returns the nearest long integer to x, consistent with the
current rounding mode. It raises an invalid floating-point exception if
the magnitude of the rounded value is too large to represent. And it
raises an inexact floating-point exception if the return value does not
equal x.

The output of the following program does not make sense to me.

lrint(+1.500000)=2
lrint(+2.500000)=2

How could 1.5 AND 2.5 be rounded to 2 in the same rounding mode?

I have seen it called the "banker rounding" (in spanish, but I suppose
it should be the same in english.

If the fractional part of the number is less than 0.5, it is rounded
down. If it is more than 0.5, it is rounded up. If it is exactly 0.5,
then if the integral part is odd, it is rounded up, else it is rounded
down.

It makes the rounding smoother, and the probability of accounting and
audit results being the same, higher.

"Round toward the nearest integer with the closer value, or toward the
nearest even integer if two integers are equally near."

Therefore, by definition, "round to nearest" in C and C++ is different
from the mathematicians' "round to nearest".

In math, 2.5 is rounded to 3. In C++, 2.5 is rounded to 2.

Thanks for making me aware of this fact.
Sep 18 '07 #3
On Sep 18, 11:20 am, Spoon <root@localhostwrote:
I don't understand how the lrint() function works.
long lrint(double x);
Just a technicality, but this function doesn't exist (yet) in
C++; it's part of C99. (On the other hand, it will be part of
the next C++ standard, and I would expect most implementations
of C++ to support it already.)
The function returns the nearest long integer to x, consistent with the
current rounding mode. It raises an invalid floating-point exception if
the magnitude of the rounded value is too large to represent. And it
raises an inexact floating-point exception if the return value does not
equal x.
The output of the following program does not make sense to me.
#include <cstdio>
#include <cmath>
int main()
{
for (int i=-10; i < 10; ++i)
{
double x = i + 0.5;
printf("lrint(%+f)=%ld\n", x, lrint(x));
}
return 0;

}
\$ g++ -std=c++98 -Wall -Wextra -O2 -march=pentium3 foo.cxx -lm
\$ ./a.out
lrint(-9.500000)=-10
lrint(-8.500000)=-8
lrint(-7.500000)=-8
lrint(-6.500000)=-6
lrint(-5.500000)=-6
lrint(-4.500000)=-4
lrint(-3.500000)=-4
lrint(-2.500000)=-2
lrint(-1.500000)=-2
lrint(-0.500000)=0
lrint(+0.500000)=0
lrint(+1.500000)=2
lrint(+2.500000)=2
lrint(+3.500000)=4
lrint(+4.500000)=4
lrint(+5.500000)=6
lrint(+6.500000)=6
lrint(+7.500000)=8
lrint(+8.500000)=8
lrint(+9.500000)=10
How could 1.5 AND 2.5 be rounded to 2 in the same rounding mode?
Those are the rules for IEEE round to nearest mode. In the case
of .5, it rounds to even. The reason for this is so that there
will be no overall bias in the rounding; if you use the
"standard" rounding, with 0.5 rounding up, you introduce a bias
towards higher values. (If you add the rounded positive values
in your example, the results will be very close to the results
of adding the unrounded values if IEEE round to nearest is used;
with the classical commercial rounding, they would be
significantly greater.)

Note that you cannot always use this rounding in commercial
software; most countries have laws concerning what is good
bookkeeping practices, and impose very specific rules of
rounding, including the fact that 0.5 cents always rounds away
from 0. (Of course, since the rules are based on decimal
values, you generally can't use double directly anyway.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Sep 19 '07 #4
On Sep 18, 12:22 pm, Zara <yoz...@terra.eswrote:
On Tue, 18 Sep 2007 11:20:45 +0200, Spoon <root@localhostwrote:
[...]
lrint(+1.500000)=2
lrint(+2.500000)=2
How could 1.5 AND 2.5 be rounded to 2 in the same rounding mode?
I have seen it called the "banker rounding" (in spanish, but I suppose
it should be the same in english.
I think you've got it backwards. In banking, .5 always rounds
away from zero. It's the specialists in numeric analysis (the
mathematiciens) who insist on round to even; it means that the
average error will be 0, instead of being slightly greater than
zero.
If the fractional part of the number is less than 0.5, it is
rounded down. If it is more than 0.5, it is rounded up. It it
is exactly 0.5, then if the integral part is odd, it is
rounded up, else it is rounded down.
It makes the rounding smoother, and the probability of
accounting and audit results being the same, higher.
Accounting and audit results will be the same if both use the
same rounding rules (including where the rounding occurs). In
most countries, these rules are imposed by law, and require that
0.005 be rounded to 0.01. (In the EU, the law actually requires
that all calculations be done with 5 decimal digits precision,
and that the final result be rounded to 2 decimal digits.) Note
too that because these rules are normally expressed in terms of
decimal arithmetic and rounding of decimal digits, you can't use
machine floating point directly.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Sep 19 '07 #5
On 2007-09-19 04:15:26 -0400, James Kanze <ja*********@gmail.comsaid:
On Sep 18, 12:22 pm, Zara <yoz...@terra.eswrote:
>On Tue, 18 Sep 2007 11:20:45 +0200, Spoon <root@localhostwrote:

[...]
>>lrint(+1.500000)=2
lrint(+2.500000)=2
>>How could 1.5 AND 2.5 be rounded to 2 in the same rounding mode?
>I have seen it called the "banker rounding" (in spanish, but I suppose
it should be the same in english.

I think you've got it backwards. In banking, .5 always rounds
away from zero. It's the specialists in numeric analysis (the
mathematiciens) who insist on round to even; it means that the
average error will be 0, instead of being slightly greater than
zero.
Nevertheless, I've also heard "round to even" called "banker's
rounding." And that most reliable of sources, Wikipedia, agrees:
http://en.wikipedia.org/wiki/Roundin...to-even_method.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Sep 19 '07 #6

### This discussion thread is closed

Replies have been disabled for this discussion.