Arduino Language Reference states: If doing math with floats, you need to add a decimal point.
And yet, it sometimes fails.
I think everybody should be aware of this.
volatile uint32_t a = 65550;
volatile uint32_t b = 65560;
void setup() {
Serial.begin(115200);
uint32_t p1 = a * b / 100; // expected to overflow 32 bits number
uint32_t p2 = a * b / 100.0; // expected to calculate in float
uint32_t p3 = float(a) * float(b) / 100.0; // sure to calculate in float
Serial.println("ImplicitConversion");
Serial.print("p1 ");
Serial.print(p1);
Serial.print(" p2 ");
Serial.print(p2);
Serial.print(" p3 ");
Serial.println(p3);
}
void loop() {}
uint32_t p2 = a * b / 100.0; // expected to calculate in float
The multiplication is being done using uint32_t, then the result converted to float for the division. Cast either a or b to float and you will get the expected answer.
Exactly my point: adding a decimal point to the third number makes one expect the calculation will be done in float.
Wrong.
But: explicit conversion of one of the variables will indeed trigger implicit conversion of the other.
It's just a feeling, but I feel like adding those parentheses decouples the third number, giving the compiler even more freedom in implementing the calculation of the first two.
Point remains: the phrase 'doing math with floats, you need to add a decimal point' gives a very much simplified view of things.
The math is always using two operands at a time (except for like negation). So in this case, integer and double is performed as double; then double and integer. Nothing particularly tricky happening.
The Arduino Language Reference is of course aimed at a non-expert user group and can oversimplify some of the underlying C++ rules for brevity. For a more detailed treatment of the subject there is this: Implicit conversions - cppreference.com
No it doesn't. calculations are done in order of priority and since the 2nd calculation does not have priority over the first, those to uint32_t variables are calculated using 32-bit integer. and then temporarily stored in one before the 2nd calculation takes place.
Since division and multiplication have equal priority, forcing a float calculation could be done either by casting or by moving the division to the left.
uint32_t p2 = b / 100.0 * a;
It is not something that you should be warned about.