Code: Select all
x.d = 0 50
y.d = 0.51
a.i = Round(x, #PB_Round_Nearest)
b.i = x
Debug a
Debug b
Code: Select all
x.d = 0 50
y.d = 0.51
a.i = Round(x, #PB_Round_Nearest)
b.i = x
Debug a
Debug b
Code: Select all
Macro test(xxx)
x.d = xxx
a.i = Round(x, #PB_Round_Nearest)
b.i = x
Debug a
Debug b
EndMacro
test(0.50)
test(0.51)
Code: Select all
1
0
1
1
It is the same as Int(), not Round()Olli wrote: Sun May 18, 2025 10:44 pm Why the non-explicit double-to-integer converter has a light different behaviour, compared to the Round() native function ?
This function returns an integer value. To get a quad value, use the IntQ() function.
The integer part is created by cutting off the fractional part of the value. There is no rounding. To perform rounding, use the Round() function.
Code: Select all
b.i = x
Code: Select all
; Step 1
x.d = 0.51
b.i = x
Debug Int(x)
Debug Round(x, #PB_Round_Nearest)
Debug b
; Step 2
x.d = 0.50
b.i = x
Debug Int(x)
Debug Round(x, #PB_Round_Nearest)
Debug b
Code: Select all
;Test code to show PureBasic's included rounding methods.
; Other methods are available through custom routines.
;
;PureBasic version 6.20
;Date of last change: 5/18/2025
EnableExplicit
Macro mcr_center(_string_, _w_, _padChar_=" ")
ReplaceString(Space(_w_ - (Len(_string_) + (_w_ - Len(_string_)) / 2)), " ", _padChar_) +
_string_ +
ReplaceString(Space((_w_ - Len(_string_)) / 2), " ", _padChar_)
EndMacro
Macro mcr_padRSet(_string_, _w_, _p_, _padChar_=" ")
ReplaceString(Space(_p_), " ", _padChar_) + RSet(_string_, _w_, _padChar_)
EndMacro
Define x.d, b.i, o$, i
Debug "Rounding Methods" + #LF$ + RSet("", 16, "=")
o$ = mcr_center("", 12) +
mcr_center("Type d->i", 12) +
mcr_center("Int()", 12) +
mcr_center("Up", 12) +
mcr_center("Down", 12) +
mcr_center("Nearest", 12)
Debug o$
o$ = mcr_center("x.d", 12) +
mcr_center("(banker's)", 12) +
mcr_center("(truncate)", 12) +
mcr_center("(ceiling)", 12) +
mcr_center("(floor)", 12) +
mcr_center("(half up)", 12) ;away from zero, to be more negative or more positive
Debug o$
o$ = ReplaceString("xxxxxx", "x", ReplaceString(" - ", "-", RSet("", 10, "-")))
Debug o$
x.d = -5.5
For i = 1 To 21
x.d + 0.5
b.i = x.d ;invokes the default rounding from float to integer used by IE 754 ('banker's rounding')
o$ = mcr_padRSet(StrD(x, 4), 8, 2) +
mcr_padRSet("" + Str(b), 10, 2) +
mcr_padRSet("" + Int(x), 10, 2) +
mcr_padRSet("" + Round(x, #PB_Round_Up), 10, 2) +
mcr_padRSet("" + Round(x, #PB_Round_Down), 10, 2) +
mcr_padRSet("" + Round(x, #PB_Round_Nearest), 10, 2)
Debug o$
Next
Code: Select all
Rounding Methods
================
Type d->i Int() Up Down Nearest
x.d (banker's) (truncate) (ceiling) (floor) (half up)
---------- ---------- ---------- ---------- ---------- ----------
-5.0000 -5 -5 -5 -5 -5
-4.5000 -4 -4 -4 -5 -5
-4.0000 -4 -4 -4 -4 -4
-3.5000 -4 -3 -3 -4 -4
-3.0000 -3 -3 -3 -3 -3
-2.5000 -2 -2 -2 -3 -3
-2.0000 -2 -2 -2 -2 -2
-1.5000 -2 -1 -1 -2 -2
-1.0000 -1 -1 -1 -1 -1
-0.5000 0 0 0 -1 -1
0.0000 0 0 0 0 0
0.5000 0 0 1 0 1
1.0000 1 1 1 1 1
1.5000 2 1 2 1 2
2.0000 2 2 2 2 2
2.5000 2 2 3 2 3
3.0000 3 3 3 3 3
3.5000 4 3 4 3 4
4.0000 4 4 4 4 4
4.5000 4 4 5 4 5
5.0000 5 5 5 5 5
Code: Select all
FPU.w
!fstcw word[v_FPU]
!mov ax, [v_FPU]
;!or [v_FPU], 0000010000000000b; down
;!or [v_FPU], 0000100000000000b; up
!or [v_FPU], 0000110000000000b; trunk
!fldcw word[v_FPU]
For n=0 To 10
f.f=n/10
i.i=f
b.i=f+0.5
Debug StrF(f,3)+" -> "+StrF(i)+" -> "+StrF(b)
Next n
Well, each of those settings is currently available through various means. There's actually 5 methods available. The one you didn't mention is "Round to nearest if equidistant". Three are obtainable with the Round() function, one with Int(). The last is obtainable in one of three ways: as a type conversion from float to integer when assigning a value to a integer variable; using the Val() of either StrD() or StrF() with a decimal value that ends in exactly '.5' and that uses 0 for the digits parameter.Michael Vogel wrote: Mon May 19, 2025 9:18 am Hi, this happens when the RC field (Rounding Control) of the FPU is set to "00" which means "Round to nearest, or to even if equidistant". You can also set the flag to "01" (Round down), "10" (Round up) or the expected "11" (toward 0).
Would be nice to have an compiler option to modify the state![]()
Yes, it does. I thank you to this observation.AZJIO wrote:Apparently b.i = x has its own simplified rounding method.
I will see if there is not already a feature request about rounding method. If no, modifying the title, I ll demand to move this subject in the 'feature request' section.Michael Vogel wrote:Would be nice to have an compiler option to modify the state
There are many operating modes because mathematically 0.5 is the same distance to both 1 and 0. That means the decision on what to do when rounding it is not clear cut. This opens things up to more than a few choices, each with their own pluses and minuses.Olli wrote: Mathematically, round 0.49 is 0 and round 0.5 is 1. But I did not know the floats hardware gave so many operating modes...