[NXC] floor function not working!!!!

Discussion specific to NXT-G, NXC, NBC, RobotC, Lejos, and more.
nxtboyiii
Posts: 366
Joined: 02 Oct 2010, 07:08
Location: Everywhere

[NXC] floor function not working!!!!

Post by nxtboyiii »

Hello,
As I was creating game I needed a float to round to the floor.
I made a test code:

Code: Select all

float x;
float y;
float ix;
float iy;
task main()
{
 while(1)
 {
   x+=0.2;
   ix=floor(x);
   NumOut(0,0,ix);
   NumOut(0,8,x);
   Wait(600);
 }
}
If you run the program, you will notice that the number above the bottom number will add by 0.2 every 600 milliseconds. Also the bottom number will show the floor of the top number. It works on some numbers but sometimes it thinks that the floor of, lets say, 2 is 1, which is incorrect, but when 2 turns to 2.2 then it says that the floor of 2.2 is 2, which is correct.
Can someone help me?

Is there a round function(nearest 100th,10th,etc)?
If not, can someone show me how?

I will just show the entire game code:

Code: Select all

int map[10][6];
float fmapx,fmapy;
int mapx,mapy;
bool gl;
int x,y;
int padd;

#define EPSILON 0.125 // Make this "as small as possible", and make sure it's a power of 2.
                      // Try 0.015625, but that may fail with larger numbers.

inline long myfloor(float x)
{
    return(x + EPSILON);
}

task dostuff()
{
 while(1)
 {
  RectOut(x,y,9,9,DRAW_OPT_FILL_SHAPE | DRAW_OPT_CLEAR);
  RectOut(0,40,100,8,DRAW_OPT_FILL_SHAPE | DRAW_OPT_CLEAR);
  if(SENSOR_1)
  {
   StopAllTasks();
  }
    if(fmapy == myfloor(fmapy))
  {
   padd=0;
  }
  else
  {
   padd=1;
  }
  if(ButtonPressed(BTNLEFT,0) && ((map[mapx-1][mapy] == 0 && map[mapx-1][mapy+padd] == 0) || fmapx > myfloor(fmapx)))
  {
 //  until(!ButtonPressed(BTNLEFT,0));
 //  PlayToneEx(500,30,1,0);
   fmapx-=0.2;
   x-=2;
   gl=1;
  }
 // mapx=(fmapx-frac(fmapx));
/*  if(fmapx == myfloor(fmapx))
  {
   gl=0;
  }*/
  if(ButtonPressed(BTNRIGHT,0) && map[mapx+1][mapy] == 0 && map[mapx+1][mapy+padd] == 0)
  {
   fmapx+=0.2;
   x+=2;
  }
  if(fmapx == myfloor(fmapx))
  {
   PlayToneEx(700,10,1,0);
   padd=0;
  }
  else
  {
   padd=1;
  }
    if(ButtonPressed(BTNCENTER,0) && map[mapx][mapy+1] == 0 && map[mapx+padd][mapy+1] == 0)
  {
   fmapy+=0.2;
   y+=2;
  }
      if(ButtonPressed(BTNEXIT,0) && ((map[mapx][mapy-1] == 0 && map[mapx+padd][mapy-1] == 0) || fmapy > myfloor(fmapy)))
  {
   fmapy-=0.2;
   y-=2;
  }
  mapy=myfloor(fmapy);
   mapx=myfloor(fmapx);
   RectOut(x,y,9,9,DRAW_OPT_FILL_SHAPE);
   NumOut(0,40,mapx);
   NumOut(15,40,fmapx);
   //NumOut(40,40,(frac(fmapx)));
   NumOut(70,40,myfloor(5));
   Wait(40);
 }
}

task draw()
{
 while(1)
 {
  for(int c=0; c < 10; c++)
  {
   for(int d=0; d < 6; d++)
   {
    if(map[c][d] == 1)
    {
     RectOut(c*10,d*10,9,9);
    }
   }
  }
 }
}

task main()
{
 SetAbortFlag(BTNSTATE_NONE);
 SetSensorTouch(S1);
 mapx=1;
 mapy=1;
 fmapx=1.0;
 fmapy=1.0;
 x=10;
 y=10;
 for(int c=0; c < 10; c++)
 {
  map[c][0]=1;
 }
  for(int c=0; c < 6; c++)
 {
  map[0][c]=1;
 }
  for(int c=0; c < 10; c++)
 {
  map[c][5]=1;
 }
  for(int c=0; c < 6; c++)
 {
  map[9][c]=1;
 }
 map[4][3]=1;
 Precedes(draw,dostuff);
}

If you run it you will encounter some problems because the floating-point values aren't exactly correct. Help? :)

Thanks,
nxtboy III
Last edited by nxtboyiii on 31 May 2011, 02:50, edited 1 time in total.
Thanks, and have a nice day,
nxtboy III

programnxt.com
linusa
Posts: 228
Joined: 16 Oct 2010, 11:44
Location: Aachen, Germany
Contact:

Re: [NXC] floor function not working!!!!

Post by linusa »

Two things come to my mind:
1.) I don't see a ClearScreen(). You should insert one to avoid the typical "what's displayed on the screen is not what's in my variable" bug.
2.) Not sure if that's the case here, BUT: Floating point arithmetics! If you think you have the number 2, it might actually be something like 1.999327 in memory. Or you might not add up exactly 0.2, but 0.199534 every time.

You generally want to avoid such round-off errors by NOT constantly adding up small numbers, but by multiplying them with a count. I.e. for certain things (such as rotation matrices from rotation angles, to give a common example), you DON'T want to add up 0.01 for 100 times, but rather calculate "100 * 0.01".

I'm not sure if you've hit this specific problem in this case (it usually doesn't show up -- when you're a bit lucky), but what I've said is true in general...
RWTH - Mindstorms NXT Toolbox for MATLAB
state of the art in nxt remote control programming
http://www.mindstorms.rwth-aachen.de
MotorControl now also in Python, .net, and Mathematica
nxtboyiii
Posts: 366
Joined: 02 Oct 2010, 07:08
Location: Everywhere

Re: [NXC] floor function not working!!!!

Post by nxtboyiii »

So how exactly would I fix it?

Could you give me some code?
Thanks, and have a nice day,
nxtboy III

programnxt.com
muntoo
Posts: 834
Joined: 01 Oct 2010, 02:54
Location: Your Worst Nightmare
Contact:

Re: [NXC] floor function not working!!!!

Post by muntoo »

Try this:

Code: Select all

#define EPSILON 0.125 // Make this "as small as possible", and make sure it's a power of 2.
                      // Try 0.015625, but that may fail with larger numbers.

inline long myfloor(float x)
{
    return(x + EPSILON);
}

myfloat(41.875) == 42
If the distance between the next closest number is less than or equal to EPSILON, round up. The smaller EPSILON is, the more "accurate" it is. But making it smaller also creates your "problem". There's no perfect answer to this; unless, of course, you stored all numbers in a string. (But that's terribly slow, so no one in their right mind uses strings for numbers.)

-----

Read up on FP Comparisons. Maybe you can steal GNU's implementation. (The algorithm isn't necessarily theirs, though.)

Also, if you're using it for game programming, do you really need floor() to be that accurate? In fact, using floor like that will only increase your errors in the long run. (It's fine if you're using it a few times, but the error compounds if you keep doing it.)

You may wish to look into RK4. (gafferongames has some great game physics tutorials. Even StackOverflow thinks so!)

(@doc-helmut: You challenged me [a long, long time ago in a galaxy far, far away] that RK4 couldn't be NXC-ized. This should be close enough.)
Image

Commit to LEGO Mindstorms Robotics Stack Exchange:
bit.ly/MindstormsSE


Commit to LEGO Stack Exchange: bit.ly/Area51LEGOcommit
nxtboyiii
Posts: 366
Joined: 02 Oct 2010, 07:08
Location: Everywhere

Re: [NXC] floor function not working!!!!

Post by nxtboyiii »

Thanks Muntoo!!!!!!!!!
It worked!!! :D * 1,000,000

EDIT: Is there a round function?(round to the nearest tenth, hundredth,etc)
If not, can someone show me how?
Thanks, and have a nice day,
nxtboy III

programnxt.com
nxtboyiii
Posts: 366
Joined: 02 Oct 2010, 07:08
Location: Everywhere

Re: [NXC] floor function not working!!!!

Post by nxtboyiii »

Can anybody help? I was wondering how to make a function that rounds a number to the nearest tenth.
Thanks, and have a nice day,
nxtboy III

programnxt.com
linusa
Posts: 228
Joined: 16 Oct 2010, 11:44
Location: Aachen, Germany
Contact:

Re: [NXC] floor function not working!!!!

Post by linusa »

Multiple the number in question by 10, use your existing method (to round to the nearest integer), and then divide the resulting number by 10.
RWTH - Mindstorms NXT Toolbox for MATLAB
state of the art in nxt remote control programming
http://www.mindstorms.rwth-aachen.de
MotorControl now also in Python, .net, and Mathematica
nxtboyiii
Posts: 366
Joined: 02 Oct 2010, 07:08
Location: Everywhere

Re: [NXC] floor function not working!!!!

Post by nxtboyiii »

Hopefully that will work so the float won't be messed up. I will try it later today.

Like this:

Code: Select all

float roundto10th(float x)
{
 float mul=x*10;
 int mfloor=mul;
 float output=mfloor/10;
 return(output);
}
EDIT: afanofosc do you think you could help me on this?
Thanks, and have a nice day,
nxtboy III

programnxt.com
linusa
Posts: 228
Joined: 16 Oct 2010, 11:44
Location: Aachen, Germany
Contact:

Re: [NXC] floor function not working!!!!

Post by linusa »

In that case, don't forget the + 0.5, otherwise you're not rounding:

Code: Select all

int mfloor=mul+0.5;
RWTH - Mindstorms NXT Toolbox for MATLAB
state of the art in nxt remote control programming
http://www.mindstorms.rwth-aachen.de
MotorControl now also in Python, .net, and Mathematica
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: [NXC] floor function not working!!!!

Post by HaWe »

... or -0.5 for negative numbers...
but nxtboyiii,
if you want to round, why don't you use the round() function instead of floor() and ceil() ?
Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests