I had the issue that
voltage = voltage*2/3;
and
voltage *= 2/3;
gave different results. The variable is uint16_t
and is running on an 8bit AVR microcontroller
First statement gave the correct result, second statement always returned 0.
Some friends of mine told me that unary operators should not be used in general which made me think since I also use things like PORTC &= ~(1 << csBit);
. For compiling, I use avr-gcc if that might give you an idea.
Thanks in advance for your help
edit#1:
OK, I understood that = is not an unary operator. Also the underlying difference is that '''=''' is starting from the right and ''''*, /''' is starting from left.
I guess for uints, both statements are not correct and I would have to write voltage = (uint16_t)((float)voltage*(float)2/3)
and thanks @Lundin for pointing out how to correctly react to replies
CodePudding user response:
voltage = voltage*2/3
multiplies voltage
by 2, divides by 3, and stores the result in voltage
.
voltage *= 2/3
divides 2 by 3, multiplies the result by voltage
and stores the result of that in voltage
. Integer division truncates, so 2/3
produces zero.
None of those are unary operators.
CodePudding user response:
You’re being bitten by a combination of differing order of operations and integer arithmetic.
Arithmetic operators are left-associative, so
voltage = voltage * 2 / 3;
is parsed as
voltage = (voltage * 2) / 3;
you’re dividing the result of voltage * 2
by 3
, whereas
voltage *= 2 / 3;
is equivalent to
voltage = voltage * (2 / 3);
you’re multiplying voltage
by the result of 2/3
, which is 0
.
The problem isn’t so much the *=
, the problem is that
(a * b) / c != a * (b / c)
CodePudding user response:
the difference is that in voltage = voltage * 2 / 3, voltage is multiplied by 2 and the result divided by 3:
voltage = 5
5 * 2 = 10
10 / 3 = 3
while in voltage * = 2 / 3, since you are using uint16_t, and therefore the decimals are truncated it is first performed 2/3 and the result multiplied by voltage:
votage = 5
2 / 3 = 0
voltage = 5 * 0 = 0
to avoid this you should, for example make the calculation run in floating point before it is assigned to voltage, for example by adding ".0" somewhere:
voltage = voltage * 2.0 / 3 = 3
voltage *= 2.0 / 3 = 3