## Round a number function problem

General FreeBASIC programming questions.
BasicCoder2
Posts: 3614
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
fxm
Posts: 10036
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

### Re: Round a number function problem

Simply CINT !
BasicCoder2
Posts: 3614
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.

Code: Select all

`screenres 640,480,32dim as single iifor i as single = -3 to 3 step 0.3    print i;tab(20);CInt(i)    print "----------------------------------------------"next isleep`
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

### 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))nextsleep`

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`
fxm
Posts: 10036
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

### Re: Round a number function problem

Same result with the FB keyword CINT:

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))nextsleep`

In fact the rounding depends on program context!
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

### Re: Round a number function problem

fxm wrote:Same result with the FB keyword CINT
...
In fact the rounding depends on program context!

Yes, that is the result I get, but why would the result vary with the context?
fxm
Posts: 10036
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

### Re: Round a number function problem

Depending on program calculation context!

The BasicCoder2's code, but just with 'step=0.5':

Code: Select all

`screenres 640,480,32for i as single = -3 to 3 step 0.5    print i;tab(20);CInt(i)    print "----------------------------------------------"next isleep`
Posts: 2176
Joined: May 24, 2007 22:10
Location: The Netherlands

### Re: Round a number function problem

Remove sign, then add sign again, something like this?

Code: Select all

`dim as single adim as integer i, jfor i = -10 to +10   a = i * 0.3   j = int(abs(a)+0.5)*sgn(a)   print a, jnext`
D.J.Peters
Posts: 8203
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

Code: Select all

`union U_SNG  as single s  as ulong  uend unionfunction 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 ifend functionunion U_DBL  as double   d  as ulongint uend unionfunction 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 ifend functiondim as single  sidim as double  didim as integer jdim as longint kfor si = -3 to +3 step .25  di=si  j = SNGRound(si)  k = DBLRound(di)  print si,j,knextsleep`
MrSwiss
Posts: 3657
Joined: Jun 02, 2013 9:27
Location: Switzerland

### 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   EndIfEnd FunctionFunction 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   EndIfEnd Functiondim as single  sidim as double  didim as Long j'Dim as Integer jdim as longint kfor si = -3 to +3 step .25  di=si  j = SNGRound(si)  k = DBLRound(di)  print si,,j,,knextsleep`
BasicCoder2
Posts: 3614
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

Code: Select all

`screenres 640,480,32locate 1,1for i as single = -3.0 to 3.0 step 0.3    print i;tab(25);CInt(i)    print "----------------------------------------------"next isleepclslocate 1,1for i as double = -3.0 to 3.0 step 0.3    print i;tab(25);CInt(i)    print "----------------------------------------------"next iwhile inkey<>"":wendwhile inkey="":wend`

.
D.J.Peters
Posts: 8203
Joined: May 28, 2005 3:28
Contact:

### Re: Round a number function problem

MrSwiss wrote:Simpler version (no unions):

@MrSwiss "Simpler" does not mean better
BasicCoder2
Posts: 3614
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.
Something like this although this one looks to me like yours it doesn't work properly.

Code: Select all

`screenres 640,480,32function round(n as single) as integer    return int(abs(n)+0.5)*sgn(n)end functionfor i as single = -3 to 3 step 0.3    print i,round(i)    print "--------------------------------"next isleep`

.
BasicCoder2
Posts: 3614
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.

Code: Select all

`screenres 640,480,32color rgb(0,0,0),rgb(255,255,255):clsfor 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 isleep`
Posts: 2176
Joined: May 24, 2007 22:10
Location: The Netherlands

### Re: Round a number function problem

Whereas the Single returns 3 the Double returned 2.999999999999999

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.