bmx-ng / bcc

A next-generation bcc parser for BlitzMax
zlib License
33 stars 13 forks source link

Add native "round()" command #582

Open GWRon opened 2 years ago

GWRon commented 2 years ago

We have floor() and ceil() to round integers downwards (to negative infinity) or upwards (to positive infinity).

ceil(0.6) = 1
floor(0.6 = 0

ceil(-1.1) = -1
floor(-1.1) = -2

Often we use this here: value = int(floatValue + 0.5) to avoid stuff like casting 3.0:float to integer (which can mean int(2.9999997) or int(3.000001)).

To avoid this issue we should compare the sgn() of the value ... or written differently:

if floatValue < 0
  value = int(floatValue - 0.5)
else
  value = int(floatValue + 0.5)
endif

or maybe it could be written this way:

value = int(floatValue + 0.5 - (floatValue < 0))

I think it would be good to have a native round() command which does a similar thing for the developer (in C we can of course write it ... shorter).

Having a round() command at hand might avoid issues as most people will most likely have used the old intValue = int(floatValue + 0.5)

Kerntrick commented 2 years ago
Function Round:Double(x:Double) Inline
    Return Floor(x + 0.5)
End Function
GWRon commented 2 years ago

https://stackoverflow.com/questions/47302544/why-do-lots-of-old-programs-use-floor0-5-input-instead-of-roundinput and also this here https://stackoverflow.com/questions/485525/round-for-float-in-c/24348037#24348037

The classic "+ 0.5" might have an issue with values like 0.49999999999999994 (Round(variable which was calculated and is 0.5)) which could become 1 or 0.

Hmm... seems I opened a can of worms.