How to actually convert float to int?

int(float) returns wildly wrong values... I get that this is some kind of conversion error to be expected, I'm working with a float like 12345.67 and it comes out to weird numbers.

...but I really need to get an int from a float that is correct. I've been all over these forums and the internet and I can't find the answer. I need the INT so I can display the number on an LCD in a good way.

Thank you

maybe..

int(trunc(float))

good luck.. ~q

1 Like

If you want to extract 12345 from 12345.67, then execute the following sketch:

void setup() 
{
  Serial.begin(9600);
  float y = 12345.67;
  int y2 = (int)y;
  Serial.print(y2, DEC);

}

void loop(){}

int altDisplay = int(trunc(altitude));

My dude! Thank you so much!!!

wait no

I'm still getting weird values for 5 digit numbers

1 Like

overflowing int.. use long..

~q

1 Like

This is exactly what is producing the weird numbers. I am trying to int(123456.78) and it comes out as some 5 digit number.


float pressure = bmx280.getPressure();
unsigned int pressureDisplay = int(trunc(pressure));
Serial.print(pressure); Serial.print(" "); Serial.print(pressureDisplay);

82364.00 16828

that was it, use long instead. Thank you good person!

1 Like

You need to study various data types:
1. int type variable can hold numbers from -32768 to 32767 (0x8000 - 0x0000 - 0x7FFF)
2. unsigned int type variable can hold: 0 - 65535 (0x0000 - 0xFFFF)
3. long int type variable can hold: -2147483648 to 2147483647
4. unsigned long int type variable can hold: 0 to 18 446 744 073 709 551 615

1 Like

Yeah. I'm a full time python dev and game developer, I just don't write in languages that use typing in that way, for the most part, JS, python, C#. I studied C back in the day but it has been a long time. Only been a few weeks into the arduino stuff this go-round on it. Can probably stand to read some docs but I think I have 99% of what I need now :slight_smile:

1 Like

actually their all native types..
meaning their size depends on what you compile too..
could be 16 bit or 32..
there are also int16_t, int32_t to name a few, which are non native and always certain size..

have fun.. ~q

1 Like

Probably don’t even need a cast

float f = 123.456;
long l = f;

Should work

1 Like

I make sure i dont use the int data type. On avr its 16 bit, on arm its 32 bit. Have been caught out with this before

I much prefer to be explicit
uint8_t
int8_t
uint16_t
int16_t
uint32_t
int32_t

2 Likes

And if you want to round your float instead of truncate it, one way is to add 0.5, thus...

void setup() {
  Serial.begin(115200);

  float f = 123.499;
  long l = f + 0.5;
  Serial.println(l);

  f = 123.5;
  l = f + 0.5;
  Serial.println(l);

  f = 123.501;
  l = f + 0.5;
  Serial.println(l);
}

...which gives this:

123
124
124

It depends on the value you are trying to represent.
Suppose you read a voltage on the ADC and do the conversion to convert to a (float) voltage between 0 and 5.000 V.
Converting that to an integer and displaying that as 0, 1, 2 etc would lose a lot of the resolution of the ADC.
If you convert to (float) microvolts ( between 0 and 5000000.000)
then convert and display as an integer you give the user a misleading idea of the resolution.

What is "correct" depends on what the numbers represent.

I will read it as: a float value is being assigned to a long type integer variable -- is my reading logically correct? If not, then you are correct; else, I will use cast (long int)f to extract the integer part from the float.

What i meant is that in C++, when you assign a float to a long type, the specification allows for implicit conversion so it’s OK to write that directly.

But…. the C++ standard does not define the exact behavior for this conversion, as it depends on the implementation and the specific platform (so different C++ compilers could handle floating-point to integral conversions slightly differently - specific optimizations or rounding behaviors can lead to variations in results).

There are two key points to remember even in our scenario where both float and long are 32-bit on a platform that follows IEEE 754 representation for float.

  • it's possible for a float (approximately from -3.4 x 10^38 to 3.4 x 10^38, without precisely representing all integers within this range) to exceed the representable range of a long (-2,147,483,648 to 2,147,483,647). The implicit conversion will cause an overflow when you assign it to a long. The behavior is undefined in C++ for signed integer overflow, which means you cannot predict the result.

  • if the float value is within the range of long, due to the limited precision of float, there might be rounding errors or loss of precision when converting from float to long. You have to be OK with that approximation.

By using int for the target type, OP fell in the first case, where the implicit conversion type was not large enough.

If you don’t want dependencies on compiler for the rounding and have a known outcome you first use std::round() or std::ceil() or std::floor(). This gives you still a floating point (double) value but with no fractional part in a defined way. Then you need to decide the suitable (large enough) target type if you want to deal with integral numbers. You can choose from int8_t to int64_t and can use a static cast for this to make your intention clear. (Or use other large integral number custom classes which offer even larger types)

1 Like

Understanding your text by examples:

Given:

float y = 3.456789123E10;   // y > 2147483647
long y1 = y;
Serial.println(y1);// shows: 2147483647

//-------------------------------------------------

float y = 3.4567891234E8; // y < 2147483647
long y1 = y;    //implicit conversion
Serial.println(y1);// shows: 345678912

Indeed, interesting!

loss of precision when converting from float to long

@GolamMostafa, @J-M-L Firstly, I don't have an Arduino here to test with.
However, don't assume your result is due to the long conversion. Just because one assigned a value 3.456789123 to the float, does NOT mean the float retains that full value to the last digit. It may be that all that was retained in the float's internal representation was 3.45678912, so the long conversion is completely accurate - what's there, is still there, it's just that what's there, isn't what you think should be there.

I'd start by printing the float with maximum resolution, before doing the assignment to long. If that's not conclusive, then dig into the underlying four-byte storage of the float, extracting the bits used for mantissa, signs, etc. Google IEEE754 for more info, if needed.
Not saying you're wrong, just pointing out that there are two places where your conversion may have limited.

Given:
float y = 3.456789123;

void setup()
{
  Serial.begin(9600);
  float y = 3.456789123;
  Serial.println(*(long*)&y, HEX); //32-it IEE-754 value:405D3C08
  float y1;
  *(long*)&y1 = 0x405D3C08;
  Serial.println(y1, 19); //shows:3.4567890167236328125; 7-digit accuracy
}

void loop() {}

Manual Calculation:

Try

  float y = 3.456789123;
  Serial.begin(9600);
  Serial.println(y, 19);