Page 1 of 2

[NXC] convert float to int

Posted: 29 May 2011, 21:20
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.

Re: [NXC] convert float to int

Posted: 29 May 2011, 21:32
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

Re: [NXC] convert float to int

Posted: 29 May 2011, 22:15
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.

Re: [NXC] convert float to int

Posted: 29 May 2011, 22:45
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...

Re: [NXC] convert float to int

Posted: 30 May 2011, 14:50
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!

Re: [NXC] convert float to int

Posted: 31 May 2011, 00:48
by muntoo
Technically, the round() method is usually implemented as such:

Code: Select all

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

Re: [NXC] convert float to int

Posted: 31 May 2011, 07:48
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. :-)

Re: [NXC] convert float to int

Posted: 31 May 2011, 08:40
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?

Re: [NXC] convert float to int

Posted: 01 Jun 2011, 13:56
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

Re: [NXC] convert float to int

Posted: 01 Jun 2011, 14:19
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