Round a number function problem
-
- Posts: 3906
- Joined: Jan 01, 2009 7:03
- Location: Australia
Round a number function problem
Are there any math brains here that can show me a simple way to round a single (or double) float value to a rounded value like this using FreeBASIC?
declare function ROUND(f as float) r as integer
input output
SINGLE ROUNDED
-3.0 -3
-2.7 -3
-2.4 -2
-2.1 -2
-1.8 -2
-1.5 -2
-1.2 -1
-0.9 -1
-0.6 -1
-0.3 0
0.0 0
+0.3 0
+0.6 +1
+0.9 +1
+1.2 +1
+1.5 +2
+1.8 +2
+2.1 +2
+2.4 +2
+2.7 +3
+3.0 +3
declare function ROUND(f as float) r as integer
input output
SINGLE ROUNDED
-3.0 -3
-2.7 -3
-2.4 -2
-2.1 -2
-1.8 -2
-1.5 -2
-1.2 -1
-0.9 -1
-0.6 -1
-0.3 0
0.0 0
+0.3 0
+0.6 +1
+0.9 +1
+1.2 +1
+1.5 +2
+1.8 +2
+2.1 +2
+2.4 +2
+2.7 +3
+3.0 +3
Re: Round a number function problem
Simply CINT !
-
- Posts: 3906
- Joined: Jan 01, 2009 7:03
- Location: Australia
Re: Round a number function problem
Almost. I notice that 1.5 becomes 1 but -1.5 becomes -2 in the code example below.
So the round up/down rule for .5 isn't symmetrical between positive and negative number in this program.
So the round up/down rule for .5 isn't symmetrical between positive and negative number in this program.
Code: Select all
screenres 640,480,32
dim as single ii
for i as single = -3 to 3 step 0.3
print i;tab(20);CInt(i)
print "----------------------------------------------"
next i
sleep
Re: Round a number function problem
I would have guessed that CINT uses the CRT, but apparently not.
Code: Select all
#include "crt.bi"
dim as single a1(0 to 20) = {-3.0,-2.7,-2.4,-2.1,-1.8,-1.5,-1.2,-0.9,-0.6, _
-0.3, 0.0,+0.3,+0.6,+0.9,+1.2,+1.5,+1.8,+2.1, _
+2.4,+2.7,+3.0 }
dim as double a2(0 to 20) = {-3.0,-2.7,-2.4,-2.1,-1.8,-1.5,-1.2,-0.9,-0.6, _
-0.3, 0.0,+0.3,+0.6,+0.9,+1.2,+1.5,+1.8,+2.1, _
+2.4,+2.7,+3.0 }
for i as integer = 0 to 20
print a1(i);chr(9);rintf(a1(i));chr(9);rint(a2(i))
next
sleep
Code: Select all
-3 -3 -3
-2.7 -3 -3
-2.4 -2 -2
-2.1 -2 -2
-1.8 -2 -2
-1.5 -2 -2
-1.2 -1 -1
-0.9 -1 -1
-0.6 -1 -1
-0.3 -0 -0
0 0 0
0.3 0 0
0.6 1 1
0.9 1 1
1.2 1 1
1.5 2 2
1.8 2 2
2.1 2 2
2.4 2 2
2.7 3 3
3 3 3
Re: Round a number function problem
Same result with the FB keyword CINT:
In fact the rounding depends on program context!
Code: Select all
#include "crt.bi"
dim as single a1(0 to 20) = {-3.0,-2.7,-2.4,-2.1,-1.8,-1.5,-1.2,-0.9,-0.6, _
-0.3, 0.0,+0.3,+0.6,+0.9,+1.2,+1.5,+1.8,+2.1, _
+2.4,+2.7,+3.0 }
dim as double a2(0 to 20) = {-3.0,-2.7,-2.4,-2.1,-1.8,-1.5,-1.2,-0.9,-0.6, _
-0.3, 0.0,+0.3,+0.6,+0.9,+1.2,+1.5,+1.8,+2.1, _
+2.4,+2.7,+3.0 }
for i as integer = 0 to 20
print a1(i);chr(9);rintf(a1(i));chr(9);rint(a2(i));chr(9);cint(a1(i));chr(9);cint(a2(i))
next
sleep
Re: Round a number function problem
Yes, that is the result I get, but why would the result vary with the context?fxm wrote:Same result with the FB keyword CINT
...
In fact the rounding depends on program context!
Re: Round a number function problem
Depending on program calculation context!
The BasicCoder2's code, but just with 'step=0.5':
The BasicCoder2's code, but just with 'step=0.5':
Code: Select all
screenres 640,480,32
for i as single = -3 to 3 step 0.5
print i;tab(20);CInt(i)
print "----------------------------------------------"
next i
sleep
Re: Round a number function problem
Remove sign, then add sign again, something like this?
Code: Select all
dim as single a
dim as integer i, j
for i = -10 to +10
a = i * 0.3
j = int(abs(a)+0.5)*sgn(a)
print a, j
next
-
- Posts: 8586
- Joined: May 28, 2005 3:28
- Contact:
Re: Round a number function problem
In case of SINGLE you can cast it as ULONG and clear the sign before call INT().
In case of DOUBLE you can cast it as ULONGINT and clear the sign before call INT().
here are:
function SNGRound(x as single) as integer
function DBLRound(x as double) as longint
Joshy
In case of DOUBLE you can cast it as ULONGINT and clear the sign before call INT().
here are:
function SNGRound(x as single) as integer
function DBLRound(x as double) as longint
Joshy
Code: Select all
union U_SNG
as single s
as ulong u
end union
function SNGRound(x as single) as integer
dim as U_SNG u=any
u.s = x + .5
dim as ulong s = u.u and &H80000000
if s then
u.u = u.u and &H7FFFFFFF
u.u = int(u.s)
return &HFFFFFFFF - u.u
else
return int(u.s)
end if
end function
union U_DBL
as double d
as ulongint u
end union
function DBLRound(x as double) as longint
dim as U_DBL u=any
u.d = x + .5
dim as ulongint s = u.u and &H8000000000000000
if s then
u.u = u.u and &H7FFFFFFFFFFFFFFF
u.u = int(u.d)
return &HFFFFFFFFFFFFFFFF - u.u
else
return int(u.d)
end if
end function
dim as single si
dim as double di
dim as integer j
dim as longint k
for si = -3 to +3 step .25
di=si
j = SNGRound(si)
k = DBLRound(di)
print si,j,k
next
sleep
Re: Round a number function problem
Simpler version (no unions):
Code: Select all
Function SNGRound (ByVal s As Single) As Long
Dim As Long ti
If s < 0.0 Then
s -= .000001 ' add/subtract bias
s *= -1 ' switch sign
ti = CLng(s) ' convert
ti *= -1 ' switch sign
Return ti
Else
s += .000001 ' add/subtract bias
Return CLng(s) ' convert
EndIf
End Function
Function DBLRound (ByVal d As Double) As LongInt
Dim As LongInt ti
If d < 0.0 Then
d -= .0000000001 ' add/subtract bias
d *= -1 ' switch sign
ti = CLngInt(d) ' convert
ti *= -1 ' switch sign
Return ti
Else
d += .0000000001 ' add/subtract bias
Return CLngInt(d) ' convert
EndIf
End Function
dim as single si
dim as double di
dim as Long j
'Dim as Integer j
dim as longint k
for si = -3 to +3 step .25
di=si
j = SNGRound(si)
k = DBLRound(di)
print si,,j,,k
next
sleep
-
- Posts: 3906
- Joined: Jan 01, 2009 7:03
- Location: Australia
Re: Round a number function problem
So much to digest! Thank you for all your inputs.
The difference between Single and Double surprised me as well.
Whereas the Single returns 3 the Double returned 2.999999999999999
.
The difference between Single and Double surprised me as well.
Whereas the Single returns 3 the Double returned 2.999999999999999
Code: Select all
screenres 640,480,32
locate 1,1
for i as single = -3.0 to 3.0 step 0.3
print i;tab(25);CInt(i)
print "----------------------------------------------"
next i
sleep
cls
locate 1,1
for i as double = -3.0 to 3.0 step 0.3
print i;tab(25);CInt(i)
print "----------------------------------------------"
next i
while inkey<>"":wend
while inkey="":wend
-
- Posts: 8586
- Joined: May 28, 2005 3:28
- Contact:
Re: Round a number function problem
@MrSwiss "Simpler" does not mean betterMrSwiss wrote:Simpler version (no unions):
your code used multiplication :-(
-
- Posts: 3906
- Joined: Jan 01, 2009 7:03
- Location: Australia
Re: Round a number function problem
I had the same thoughts and the way you did it seems to work but I wanted it as a function.badidea wrote:Remove sign, then add sign again, something like this?
Something like this although this one looks to me like yours it doesn't work properly.
Code: Select all
screenres 640,480,32
function round(n as single) as integer
return int(abs(n)+0.5)*sgn(n)
end function
for i as single = -3 to 3 step 0.3
print i,round(i)
print "--------------------------------"
next i
sleep
-
- Posts: 3906
- Joined: Jan 01, 2009 7:03
- Location: Australia
Re: Round a number function problem
Just to clarify the problem the context is wanting to plot a reflection of pixels around some center point.
The data is in the form of floats but a pixel has an integer value but negative and positive floats are round down instead of away from the center point. Apparently there are four ways of rounding numbers and the dividing point 0.5 can be chosen either up or down but I would at least want it to be consistent for positive and negative numbers.
The data is in the form of floats but a pixel has an integer value but negative and positive floats are round down instead of away from the center point. Apparently there are four ways of rounding numbers and the dividing point 0.5 can be chosen either up or down but I would at least want it to be consistent for positive and negative numbers.
Code: Select all
screenres 640,480,32
color rgb(0,0,0),rgb(255,255,255):cls
for i as single = -100.0 to 100.0 step 2.3
if i<0 then color rgb(255,0,0)
if i>0 then color rgb(0,0,255)
pset (i+320,240)
line (320,0)-(320,238),rgb(0,255,0)
line (320,242)-(320,479),rgb(0,255,0)
next i
sleep
Re: Round a number function problem
I expect that exactly 3 does not exist for single and double floats. the difference between 3 and 2.999999999999999 is maybe a print formatting issue.Whereas the Single returns 3 the Double returned 2.999999999999999