PureBasic Forum
https://www.purebasic.fr/english/

Inconsistent application of banker's rounding
https://www.purebasic.fr/english/viewtopic.php?f=4&t=44330
Page 1 of 1

Author:  blueznl [ Mon Nov 15, 2010 9:52 pm ]
Post subject:  Inconsistent application of banker's rounding

Code:
zero.f = 0
onehalf.f = 1.5
three.f = 3
four.f = 4

i.l = 3.0 + 1.5
Debug i

j.l = 4.0 + 1.5
Debug j

k.l = onehalf + three
Debug k

l.l = onehalf + four
Debug l


Triggered by this thread:

viewtopic.php?f=13&t=44309&p=339143#p339143

Author:  luis [ Mon Nov 15, 2010 10:55 pm ]
Post subject:  Re: Inconsistent application of banker's rounding

wow, nice find !

Code:
;
; i.l = 3.0 + 1.5
  MOV    dword [v_i],5
; Debug i
;
; j.l = 4.0 + 1.5
  MOV    dword [v_j],6
; Debug j
;
; k.l = onehalf + three
  FLD    dword [v_onehalf]
  FADD   dword [v_three]
  FADD   dword [F1]
  FISTP  dword [v_k]
; Debug k
;
; l.l = onehalf + four
  FLD    dword [v_onehalf]
  FADD   dword [v_four]
  FADD   dword [F1]
  FISTP  dword [v_l]
; Debug l


In the first two expressions the compiler pre-calculate the resulting constants (3.0+1.5 and 4.0+1.5) rounding them to the highest int and assign them directly to the long vars (not applying the "banker's rounding")

In the last two expressions involving float vars, the compiler generate the floating point instructions for the cpu resulting in the correct "banker's rounding".


EDIT: oh, I saw you already guessed it ! :)

blueznl wrote:
... my suspicion is that the compiler tries to optimize 3.0 + 1.5 and uses a regular 'normal rounding' rule, whilst the other calculation is done inside the FPU and is then converted back to integer following some IEEE standard.

Author:  Little John [ Tue Nov 16, 2010 6:51 pm ]
Post subject:  Re: Inconsistent application of banker's rounding

I think this is one more good example of the risks of implicit typecasting. In cases like this, it's safer to use Int() or Round(), e.g.

Code:
zero.f = 0
onehalf.f = 1.5
three.f = 3
four.f = 4

i.l = Round(3.0 + 1.5, #PB_Round_Nearest)
Debug i

j.l = Round(4.0 + 1.5, #PB_Round_Nearest)
Debug j

k.l = Round(onehalf + three, #PB_Round_Nearest)
Debug k

l.l = Round(onehalf + four, #PB_Round_Nearest)
Debug l

Regards, Little John

Author:  Michael Vogel [ Tue Nov 16, 2010 7:08 pm ]
Post subject:  Re: Inconsistent application of banker's rounding

Little John wrote:
I think this is one more good example of the risks of implicit typecasting. [...]


Wouldn't it be fine to get the full power (for confusion):

Code:
; just some ideas how type casting could be seen in PB5.02
i.l = {long} (3.0 + {byte} 1.5);
j.l = {long} 4.0 + {long} ( {float} 3/2 )

Author:  PB [ Tue Nov 16, 2010 9:48 pm ]
Post subject:  Re: Inconsistent application of banker's rounding

@blueznl:
But is it a bug to store the results of a float in a long?
Fred once told me never to do that, so I always use
floats to hold the results. If you change all your ".l"
to ".f" in your first post, then all results are correct.

Author:  blueznl [ Wed Nov 17, 2010 12:01 am ]
Post subject:  Re: Inconsistent application of banker's rounding

I agree it may not make much sense to store the result in an int, but that isn't the point. I just wanted to point out the behaviour is inconsistent, which is something nobody wants I guess :-)

Author:  PeterH [ Sun Dec 17, 2017 3:13 am ]
Post subject:  Re: Inconsistent application of banker's rounding

Not having owned PB for that many years, this surprised me a bit.

Two weeks of late nights with debugging and tinkering, just to find that I stumbled upon a 7 year old (still not fixed) bug. Pure chance that I even found this thread. I am going to get so hammered now.

Author:  Dude [ Sun Dec 17, 2017 6:24 am ]
Post subject:  Re: Inconsistent application of banker's rounding

If you want to use floats, then make your data types floats, as mentioned above. Not a bug.

Author:  luis [ Sun Dec 17, 2017 12:19 pm ]
Post subject:  Re: Inconsistent application of banker's rounding

Dude wrote:
Not a bug.


It's a bug.

Assigning floats to integers it's a normal, legal, mundane operation.
As LJ says, you can use explicit rounding functions if you think the compiler will behave incoherently or in a way which doesn't fit your requirements, to make sure you will get what you intended to.
But it may not be required if the compiler behave in a consistent way which does align with your requirements.
All it's fine if the assignment of a float to an int is treated by the compiler in a coherent way, preferably like most languages do to not make your life harder when porting code.

The destination variables used in this example are of the same type, the float values used in the expressions are exactly the same, the expressions are exactly the same.
Yet the result changes depending on the floats being expressed as immediate values or float variables containing the same values.
The compiler is incoherently giving different results for the same operations applied on the same data.

BTW: since in the first post the results are not mentioned here it is what happens currently.

Code:
zero.f = 0.0
onehalf.f = 1.5
three.f = 3.0
four.f = 4.0

i.l = 3.0 + 1.5
Debug i ; = 5 (round to next integer)

j.l = 4.0 + 1.5
Debug j ; = 6 (round to next integer)

k.l = three + onehalf
Debug k ; = 4 (banker's rounding to the nearest even integer)

l.l = four + onehalf
Debug l ; = 6 (banker's rounding to the nearest even integer)

Author:  Mistrel [ Sat Dec 23, 2017 8:29 am ]
Post subject:  Re: Inconsistent application of banker's rounding

Dude wrote:
If you want to use floats, then make your data types floats, as mentioned above. Not a bug.


I would argue that the issue is the inconsistency of the implementation. If this is the correct behavior then it should be well defined in the documentation.

Author:  Dude [ Sat Dec 23, 2017 10:01 am ]
Post subject:  Re: Inconsistent application of banker's rounding

luis wrote:
It's a bug.

I agree now, because of this comment by Fred three years ago:

Fred wrote:
It looks like a bug, the whole expression should be considered as float when a float is encountered.

Source: viewtopic.php?p=445463#p445463

Page 1 of 1 All times are UTC + 1 hour
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/