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.
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
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
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..
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);
}
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)
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.