[NXC] convert float to int

Discussion specific to NXT-G, NXC, NBC, RobotC, Lejos, and more.
ricardocrl
Posts: 117
Joined: 27 Dec 2010, 19:27

[NXC] convert float to int

Post by ricardocrl »

Is it possible to convert a float number to an integer (rounding the number to floor or ceil), becoming an integer after the operation?

From what I searched and tried, using floor() or ceil() just rounds the number, but the returning value is still a float. I'm trying to pass an integer argument to a function, that had to be calculated as a float before.

The specific example is: I have the expression "angle = 112.5*X". After calculating the angle I want to send the closest integer to PosRegSetAngle(). If I just use floor() or ceil() it doesn't work.
muntoo
Posts: 834
Joined: 01 Oct 2010, 02:54
Location: Your Worst Nightmare
Contact:

Re: [NXC] convert float to int

Post by muntoo »

This should do the conversion:

Code: Select all

#define f2i(x) float2int(x)

int float2int(float x)
{
    return(x);
}

Code: Select all

if(sin(f2i(1.5)) == sin(1.5))
{
    TextOut(0, 0, "You should not see this text.", 0);
}
C-Style casts should go on the wishlist... int(x)

-----

You don't need to explicitly (or "explicitly-implicitly", in this case :? ) convert float to int when passing arguments of a different type (in NXC).

This works fine:

Code: Select all

int add(int a, int b)
{
    return(a + b);
}

NumOut(0, 0, add(19.84, 23.999)); // Prints 42
Image

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


Commit to LEGO Stack Exchange: bit.ly/Area51LEGOcommit
ricardocrl
Posts: 117
Joined: 27 Dec 2010, 19:27

Re: [NXC] convert float to int

Post by ricardocrl »

Hm, I just noticed the following behaviours:

Code: Select all

float a = 2.5;
int b = 1;

long c = a*b; // c is equal to 2

Code: Select all

float a = -2.5;
int b = 1;

long c = a*b; // c is equal to 0

Code: Select all

float a = 2.5;
int b = -1;

long c = a*b; // c is equal to 0

Code: Select all

long c = -2.5; // c is equal to -2

Code: Select all

int a = 2.5;
int b = -1;

long c = a*b; // c is equal to -2

Code: Select all

float a = 2.5;
float b = -1;

long c = a*b; // c is equal to 0

Code: Select all

float a = -2.5;
float b = -1;

long c = a*b; // c is equal to 2
I hope that can be useful for some debugging.
muntoo
Posts: 834
Joined: 01 Oct 2010, 02:54
Location: Your Worst Nightmare
Contact:

Re: [NXC] convert float to int

Post by muntoo »

Code: Select all

long c = -2.5; // c is equal to -2
Understandable. (I would rather c = -3;, though.)

Code: Select all

float a = 2.5;
int b = -1;

long c = a*b; // c is equal to 0
Wow. :shock:

I think that may solve some bugs in one of my programs...
Image

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


Commit to LEGO Stack Exchange: bit.ly/Area51LEGOcommit
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: [NXC] convert float to int

Post by HaWe »

the mathematically correct way to round a fp value to an integer is this one:

Code: Select all

inline long round(float f)
{
  if (f>=0) return (f + 0.5);
  else  return (f - 0.5);
}
or, nested:

Code: Select all

inline long round(float f)
{
   return (f>=0? f+0.5 : f-0.5);
}
HTH!
muntoo
Posts: 834
Joined: 01 Oct 2010, 02:54
Location: Your Worst Nightmare
Contact:

Re: [NXC] convert float to int

Post by muntoo »

Technically, the round() method is usually implemented as such:

Code: Select all

inline long round(float x)
{
    return(x + 0.5);
}
Image

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


Commit to LEGO Stack Exchange: bit.ly/Area51LEGOcommit
ricardocrl
Posts: 117
Joined: 27 Dec 2010, 19:27

Re: [NXC] convert float to int

Post by ricardocrl »

I'm not that worried about the rounding. The incorrect cast is quite a big issue, I would say.

I worked around the problem in my program right now, but I will certainly get stuck with this later again, trying to understand what is wrong. I hope John had the chance to look at this topic. :-)
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: [NXC] convert float to int

Post by HaWe »

muntoo wrote:Technically, the round() method is usually implemented as such:

Code: Select all

inline long round(float x)
{
    return(x + 0.5);
}
ok, but:
1.) then what's not working for the TO's float conversion?
2.) what's about negative fp values?
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: [NXC] convert float to int

Post by afanofosc »

ricardocrl wrote: The specific example is: I have the expression "angle = 112.5*X". After calculating the angle I want to send the closest integer to PosRegSetAngle(). If I just use floor() or ceil() it doesn't work.
What do you mean by "it doesn't work"? Do you get a compiler error or the wrong value? Can you post a simple example that shows what is going wrong?

John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: [NXC] convert float to int

Post by afanofosc »

ricardocrl wrote: Hm, I just noticed the following behaviours:

I hope that can be useful for some debugging.
Could you please post the F12 code listing for these snippets. Is it possible that you have an old compiler version? Here's what the latest compiler produces:

Code: Select all


task main()
{
  {
    float a = 2.5;
    int b = 1;

    long c = a*b; // c is equal to 2
//	mov __main_7qG2_a_7qG2_001, __constValf2P5
//	mov __main_7qG2_b_7qG2_001, __constVal1
//	mul __main_7qG2_c_7qG2_001, __main_7qG2_a_7qG2_001, __constVal1
  }

  {
    float a = -2.5;
    int b = 1;

    long c = a*b; // c is equal to 0
//	mov __main_7qG2_a_7qG2_001, __constValNegf2P5
//	mov __main_7qG2_b_7qG2_001, __constVal1
//	mul __main_7qG2_c_7qG2_001, __main_7qG2_a_7qG2_001, __constVal1
  }

  {
    float a = 2.5;
    int b = -1;

    long c = a*b; // c is equal to 0
//	mov __main_7qG2_a_7qG2_001, __constValf2P5
//	mov __main_7qG2_b_7qG2_001, __constValNeg1
//	mul __main_7qG2_c_7qG2_001, __main_7qG2_a_7qG2_001, __constValNeg1
  }

  {
    long c = -2.5; // c is equal to -2
//	mov __main_7qG2_c_7qG2_001, __constValNegf2P5
  }

  {
    int ai = 2.5;
    int b = -1;

    long c = ai*b; // c is equal to -2
//	mov __main_7qG2_ai_7qG2_001, __constValf2P5
//	mov __main_7qG2_b_7qG2_001, __constValNeg1
//	mul __main_7qG2_c_7qG2_001, __main_7qG2_ai_7qG2_001, __constValNeg1
  }

  {
    float a = 2.5;
    float bf = -1;

    long c = a*bf; // c is equal to 0
//	mov __main_7qG2_a_7qG2_001, __constValf2P5
//	mov __main_7qG2_bf_7qG2_001, __constValNeg1
//	mul __main_7qG2_c_7qG2_001, __main_7qG2_a_7qG2_001, __constValNeg1
  }

  {
    float a = -2.5;
    float bf = -1;

    long c = a*bf; // c is equal to 2
//	mov __main_7qG2_a_7qG2_001, __constValNegf2P5
//	mov __main_7qG2_bf_7qG2_001, __constValNeg1
//	mul __main_7qG2_c_7qG2_001, __main_7qG2_a_7qG2_001, __constValNeg1
  }
}
Notice that I had to rename a couple variables due to a compiler bug I just ran into. NXC does not currently support identically named variables with different types defined at the same nesting level (i.e., you cannot currently have int b and float b both at the same nesting level). As far as I can tell the code generated by the latest version of the compiler is correct and should not produce zero values but I don't have an NXT handy to run the code on to verify that the value of c is non zero in all of these cases. This is with optimization level 2, btw.

John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests