math round vs banker's round

classic Classic list List threaded Threaded
16 messages Options
Reply | Threaded
Open this post in threaded view
|

math round vs banker's round

David Emerson
Hi all,

I have just discovered that the system.round function has this very odd
behavior of rounding towards an even number when the fractional part is
.5 -- in the system.round documentation this is described as "banker's
rounding"

I do not like this behavior. How can I use a more
mathematically-traditional round function, which always rounds .5 up,
and everything below .5 down?

Do I need to write this function myself?

Thanks!
~David

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: math round vs banker's round

José Mejuto
El 13/08/2013 23:47, David Emerson escribió:

> Hi all,
>
> I have just discovered that the system.round function has this very odd
> behavior of rounding towards an even number when the fractional part is
> .5 -- in the system.round documentation this is described as "banker's
> rounding"
>
> I do not like this behavior. How can I use a more
> mathematically-traditional round function, which always rounds .5 up,
> and everything below .5 down?
>
> Do I need to write this function myself?

Hello,

SimpleRoundTo I think.

Maybe documentation should be changed to add SimpleRoundTo in cross
referenced functions and note that SimpleRoundTo uses classic round
system instead bankers one.

--

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: math round vs banker's round

Sven Barth-2
In reply to this post by David Emerson

Am 13.08.2013 23:48 schrieb "David Emerson" <[hidden email]>:
>
> Hi all,
>
> I have just discovered that the system.round function has this very odd behavior of rounding towards an even number when the fractional part is .5 -- in the system.round documentation this is described as "banker's rounding"
>
> I do not like this behavior. How can I use a more mathematically-traditional round function, which always rounds .5 up, and everything below .5 down?
>
> Do I need to write this function myself?

Take a look at SetRoundMode in unit Math: http://www.freepascal.org/docs-html/rtl/math/setroundmode.html

Regards,
Sven


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: math round vs banker's round

Ludo Brands
On 08/14/2013 08:03 AM, Sven Barth wrote:

> Am 13.08.2013 23:48 schrieb "David Emerson" <[hidden email]
> <mailto:[hidden email]>>:
>>
>> Hi all,
>>
>> I have just discovered that the system.round function has this very
> odd behavior of rounding towards an even number when the fractional part
> is .5 -- in the system.round documentation this is described as
> "banker's rounding"
>>
>> I do not like this behavior. How can I use a more
> mathematically-traditional round function, which always rounds .5 up,
> and everything below .5 down?
>>
>> Do I need to write this function myself?
>
> Take a look at SetRoundMode in unit Math:
> http://www.freepascal.org/docs-html/rtl/math/setroundmode.html
>

None of the round modes gives the result OP wants. Furthermore,
SetRoundMode is a runtime setting and
  writeln(round(0.5));
  writeln(round(1.5));
results in
0
2
The compiler hard codes (x64) a movabs $0x0,%rdx and
movabs $0x2,%rdx

Ludo


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: math round vs banker's round

David Emerson
In reply to this post by Sven Barth-2
Thanks for the suggestions, guys!

José Mejuto wrote:
 > SimpleRoundTo I think.

But I want an integer result, and this returns a floating point.

Sven Barth wrote:
> Take a look at SetRoundMode in unit Math:
> http://www.freepascal.org/docs-html/rtl/math/setroundmode.html

After calling SetRoundMode(rmNearest);
I find that system.round() is still doing banker's rounding. Am I
missing something?

I don't see this TfpuRoundingMode mentioned anywhere in the
documentation, other than the "get" and "set" functions for the same.
What does it effect?


...
Anyway I guess I am going to have to write my own round() function :P

Cheers,
~David.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: math round vs banker's round

Ludo Brands
On 08/14/2013 08:47 AM, David Emerson wrote:

>
> I don't see this TfpuRoundingMode mentioned anywhere in the
> documentation, other than the "get" and "set" functions for the same.
> What does it effect?
>
It sets the 8087 registers and or SSE registers in x86 and x64 systems.
The problem is that the bankers mode rounding is the default IEEE 754
rounding and that is what the 8087 and SSE FPU's implements.

For SSE see http://www.rz.uni-karlsruhe.de/rz/docs/VTune/reference/vc148.htm
For 8087 see
http://books.google.fr/books?id=QZ9nM0nRQcYC&pg=PA244&lpg=PA244&dq=8087+rounding+mode&source=bl&ots=Vp3tSUsOeJ&sig=Jo7O9KggODpubD_ek5ZhKF-XgNc&hl=en&sa=X&ei=disLUs-zKMODhQeXxYCQCg&ved=0CEgQ6AEwBQ

Ludo
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: math round vs banker's round

Sven Barth-2
In reply to this post by David Emerson
Am 13.08.2013 23:47, schrieb David Emerson:

> Hi all,
>
> I have just discovered that the system.round function has this very
> odd behavior of rounding towards an even number when the fractional
> part is .5 -- in the system.round documentation this is described as
> "banker's rounding"
>
> I do not like this behavior. How can I use a more
> mathematically-traditional round function, which always rounds .5 up,
> and everything below .5 down?
>
> Do I need to write this function myself?
Just checked again, most FPUs only seem to support "banker's rounding",
"round up", "round down" and "truncate", so these four are the only ones
supported by FPC's and Delphi's rounding mechanism. So if you want
normal mathematical rounding then you'll need to write your own function.

Regards,
Sven
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: math round vs banker's round

Sven Barth-2
In reply to this post by David Emerson
Am 14.08.2013 08:47, schrieb David Emerson:

> Thanks for the suggestions, guys!
>
> José Mejuto wrote:
> > SimpleRoundTo I think.
>
> But I want an integer result, and this returns a floating point.
>
> Sven Barth wrote:
>> Take a look at SetRoundMode in unit Math:
>> http://www.freepascal.org/docs-html/rtl/math/setroundmode.html
>
> After calling SetRoundMode(rmNearest);
> I find that system.round() is still doing banker's rounding. Am I
> missing something?
rmNearest is banker's rounding.
> I don't see this TfpuRoundingMode mentioned anywhere in the
> documentation, other than the "get" and "set" functions for the same.
> What does it effect?
Just click on TFPURoundingMode mentioned in the link.
>
> ...
> Anyway I guess I am going to have to write my own round() function :P
>
Seems so.

Regards,
Sven
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: math round vs banker's round

Sven Barth-2
In reply to this post by Ludo Brands
Am 14.08.2013 08:38, schrieb Ludo Brands:

> On 08/14/2013 08:03 AM, Sven Barth wrote:
>> Am 13.08.2013 23:48 schrieb "David Emerson" <[hidden email]
>> <mailto:[hidden email]>>:
>>> Hi all,
>>>
>>> I have just discovered that the system.round function has this very
>> odd behavior of rounding towards an even number when the fractional part
>> is .5 -- in the system.round documentation this is described as
>> "banker's rounding"
>>> I do not like this behavior. How can I use a more
>> mathematically-traditional round function, which always rounds .5 up,
>> and everything below .5 down?
>>> Do I need to write this function myself?
>> Take a look at SetRoundMode in unit Math:
>> http://www.freepascal.org/docs-html/rtl/math/setroundmode.html
>>
> None of the round modes gives the result OP wants. Furthermore,
> SetRoundMode is a runtime setting and
>    writeln(round(0.5));
>    writeln(round(1.5));
> results in
> 0
> 2
> The compiler hard codes (x64) a movabs $0x0,%rdx and
> movabs $0x2,%rdx
There are three problems:
- if you use constants then the compiler will do the rounding at compile
time and not take into account the rounding mode (which in my opinion
can be considered a bug)
- 0.5 does not always have a direct representation as a floating point
value and thus internally it might be 0.4999999 or something like that
and thus it will be rounded to 0.4 (see also
http://bugs.freepascal.org/view.php?id=24374 )
- the rounding system and also most FPUs don't support that "normal
rounding" the OP wants and thus FPC doesn't implement it either (didn't
know up to now that banker's rounding is not the same as the rounding I
learned at school...)

Regards,
Sven
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: math round vs banker's round

Michael Schnell
On 08/14/2013 09:38 AM, Sven Barth wrote:
>
> - 0.5 does not always have a direct representation as a floating point
> value and thus internally it might be 0.4999999 or something like that
> and thus it will be rounded to 0.4 (see also
> http://bugs.freepascal.org/view.php?id=24374 )
Hmmm

AFAIU, in hardware / memory, the binary representation of -0.5 is

(sign * mantissa * 2 ** exponent ) =  (-1) * 0.5 * 2 ** 1

so this seems to be "exact"

Maybe the compiler does not calculate exactly this value when doing the
constant "-0.5". I don't consider this a problem, as IMHO, in fact any
attempt to rely on an exact value of a floating point number is erroneous.

-Michael

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: math round vs banker's round

Jonas Maebe-2
In reply to this post by Sven Barth-2

On 14 Aug 2013, at 09:38, Sven Barth wrote:

- 0.5 does not always have a direct representation as a floating point value and thus internally it might be 0.4999999 or something like that and thus it will be rounded to 0.4 (see also http://bugs.freepascal.org/view.php?id=24374 )

0.5 is one of the values that can always be represented exactly. The fractional part of IEEE 754 floating point numbers is represented as sums of negative powers of 2, i.e. 0.5, 0.25, etc.


Jonas

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: math round vs banker's round

Sven Barth-2
Am 14.08.2013 10:11, schrieb Jonas Maebe:

On 14 Aug 2013, at 09:38, Sven Barth wrote:

- 0.5 does not always have a direct representation as a floating point value and thus internally it might be 0.4999999 or something like that and thus it will be rounded to 0.4 (see also http://bugs.freepascal.org/view.php?id=24374 )

0.5 is one of the values that can always be represented exactly. The fractional part of IEEE 754 floating point numbers is represented as sums of negative powers of 2, i.e. 0.5, 0.25, etc.

It should have been "x.5" instead of "0.5" :)

What's your opinion regarding the point that the compiler does not handle the rounding mode when "Round" is inlined for constants?

Regards,
Sven

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: math round vs banker's round

Sven Barth-2
In reply to this post by Michael Schnell
Am 14.08.2013 09:55, schrieb Michael Schnell:

> On 08/14/2013 09:38 AM, Sven Barth wrote:
>>
>> - 0.5 does not always have a direct representation as a floating
>> point value and thus internally it might be 0.4999999 or something
>> like that and thus it will be rounded to 0.4 (see also
>> http://bugs.freepascal.org/view.php?id=24374 )
> Hmmm
>
> AFAIU, in hardware / memory, the binary representation of -0.5 is
>
> (sign * mantissa * 2 ** exponent ) =  (-1) * 0.5 * 2 ** 1
>
> so this seems to be "exact"
>
> Maybe the compiler does not calculate exactly this value when doing
> the constant "-0.5". I don't consider this a problem, as IMHO, in fact
> any attempt to rely on an exact value of a floating point number is
> erroneous.
I wanted to write "x.5" instead of "0.5" :)

Regards,
Sven
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: math round vs banker's round

Vincent Snijders-3


2013/8/14 Sven Barth <[hidden email]>
I wanted to write "x.5" instead of "0.5" :)

 
For any digit x, it still can be represented exactly in binary representation ...
 
Vincent

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: math round vs banker's round

Michael Schnell
On 08/14/2013 10:42 AM, Vincent Snijders wrote:

 
For any digit x, it still can be represented exactly in binary representation ...

Nope,
As the bit count of the mantissa is limited to - say - n , with  x > 2**(n-1) you will not have an exact representation of x.5.

-Michael

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: math round vs banker's round

Sven Barth-2
In reply to this post by Vincent Snijders-3
Am 14.08.2013 10:42, schrieb Vincent Snijders:


2013/8/14 Sven Barth <[hidden email]>
I wanted to write "x.5" instead of "0.5" :)

 
For any digit x, it still can be represented exactly in binary representation ...
*sigh* stupid floating point numbers...

Regards,
Sven

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal