Simple math strange behavior while subtracting

Hi, I am having an issue when calculating a simple subtraction. The result given is wrong.

When I do the operation inside the Serial.print() the result given is correct, however when doing it outside in order to use it the result is wrong. This is really strange, maybe Serial.print() does some sort of internal conversion, maybe someone with more programming knowledge can explain that to me.

int currentLoad = weightMeasureCalibration(i) - calibration[i];
Serial.print("\nCurrent load feet["); Serial.print(i); Serial.print("]: "); Serial.print(currentLoad); Serial.print("|"); 
Serial.print(currentLoad = weightMeasureCalibration(i) - calibration[i]); Serial.print("|"); Serial.print(currentLoad);
Printed result
Current load feet[0]: 30|-1|-1
Current load feet[1]: -140|13|13
Current load feet[2]: -10|-3|-3
Current load feet[3]: 85|-8|-8

weightMeasureCalibration & calibration are int.

Post complete code, or at least a complete example that will compile and demonstrates the problem. There is too much unknown about this.

+1 with Delta_G - don't post snippet

what type does weightMeasureCalibration(i) returns and what type is the calibration[] array and what happens when you call twice in a row weightMeasureCalibration(i)? is that supposed to return the same value or does this run a new calibration or something?

Serial.print(currentLoad = weightMeasureCalibration(i) - calibration[i]);

You REALLY need to investigate sequence points.

Thanks for answering

J-M-L: +1 with Delta_G - don't post snippet

what type does weightMeasureCalibration(i)returns and what type is the calibration[] array and what happens when you call twice in a row weightMeasureCalibration(i)? is that supposed to return the same value or does this run a new calibration or something?

Rggmiranda: weightMeasureCalibration & calibration are int.

J-M-L, the code is too long for posting, but the explanation below can be taken for certain, because the return of the function is verified. They return the same thing, calibration is an int, and weightMeasureCalibration(i) returns an int. calibration[] stays constant while weightMeasureCalibration() executes. weightMeasureCalibration() can vary, it is a function that measures the weight in a scale sensor, but the difference is less than 5, at the most. you can consider it as constant too (this is checked, it does not fluctuate more than that), the difference in this case is over 140 in some cases. > PaulS: > ``` > Serial.print(currentLoad = weightMeasureCalibration(i) - calibration[i]); > ``` > > > You REALLY need to investigate sequence points. PaulS, my idea is not to assign a value to currentLoad inside a Serial.print, the idea was for testing what would happen, however I want to ask you. When I print like this "Serial.println(weightMeasureCalibration())" the value looks fine, is that incorrect according to sequence points? Keep in mind that weightMeasureCalibration() is a function that would be something like an analogRead, as an example, it takes a parameter, operates to get a value, and returns the measurement.

When I print like this "Serial.println(weightMeasureCalibration())" the value looks fine, is that incorrect according to sequence points?

No. There are two sequence points - the call to the weightMeasureCalibration() function and the call to Serial.println(). Those two sequence points can only be dealt with in one order.

But, in this:

Serial.print(currentLoad = weightMeasureCalibration(i) - calibration[i]);

there are more than two sequence points, and you can't control which order the compiler will chose. The compiler could choose to print the value in currentLoad and THEN call weightMeasureCalibration() and assign a new value to currentLoad. Or it could choose to call weightMeasureCalibration() and then print the value in currentLoad and then assign it a new value. Or, it could do everything in the order that you seem to expect.

The point is that you can't rely on the compiler doing what you expect when there are multiple sequence points involved.

PaulS: Serial.print(currentLoad = weightMeasureCalibration(i) - calibration[i]);

You REALLY need to investigate sequence points.

Much much better to get out of the bad habit of putting side-effects in expressions, then no-one needs to worry about sequence points!!

Having said that array[index++] is a very handy shorthand...

Much much better to get out of the bad habit of putting side-effects in expressions, then no-one needs to worry about sequence points!!

I was hoping that OP's research would lead to that conclusion.

MarkT: Much much better to get out of the bad habit of putting side-effects in expressions, then no-one needs to worry about sequence points!!

...and the code is usually easier to read, as well

aarg: ...and the code is usually easier to read, as well

PaulS: I was hoping that OP's research would lead to that conclusion.

MarkT: Much much better to get out of the bad habit of putting side-effects in expressions, then no-one needs to worry about sequence points!!

Having said that array[index++] is a very handy shorthand...

People, my code does not use this kind of programming, lets not focus in that as if I was going to make my entire program that way. In this case I tried to print in several different ways to see what is happening with the values. Because the value of the original sentence can not be correct, this is the original part of the code. The test case was doing a calibration and then printing the result as stated below

int currentLoad = weightMeasureCalibration(i) - calibration[i];
Serial.print("\nCurrent load feet["); Serial.print(i); Serial.print("]: "); Serial.print(currentLoad); Serial.print("|");

This always has a 140 difference as show in the first message from the post. however when I print the values inside the Serial.print (as it should not be done. I know). The result looks fine.

My last question was: when I do the following "Serial.print(analogRead(A0));" for example SerialPrint takes the value returned by analogRead right? because if not it would not have anything at all to print, and in fact it does print the value read. I ask this because I tried the following:

int currentLoad = weightMeasureCalibration(i); // 
Serial.print(currentLoad ); //this returns 80 for saying something
Serial.print(weightMeasureCalibration(i));  This returns 10 for saying something.

I will check the rest of the code to find out exactly where the error comes from. I will post afterwards if I find the answer

int currentLoad = weightMeasureCalibration(i); // Serial.print(currentLoad ); //this returns 80 for saying something Serial.print(weightMeasureCalibration(i)); This returns 10 for saying something.

Unless you can guarantee that the value returned by weightMeasureCalibration() will always be the same for a given value of i (which I seriously doubt), then the fact that the two print() statements print different values should not come as a surprise.

We still need to see the weightMeasureCalibration() to know what type it is returning.

Try this:

int currentLoadOne = weightMeasureCalibration(i);
delay(100);
int currentLoadTwo = weightMeasureCalibration(i);
delay(100);
Serial.print("one: "); Serial.print(currentLoadOne); Serial.println();
Serial.print("two: "); Serial.print(currentLoadTwo); Serial.println();
Serial.print("now: "); Serial.print(weightMeasureCalibration(i)); Serial.println();

and show us the output.

PaulS: The compiler could choose to print the value in currentLoad and THEN call weightMeasureCalibration() and assign a new value to currentLoad. Or it could choose to call weightMeasureCalibration() and then print the value in currentLoad and then assign it a new value. Or, it could do everything in the order that you seem to expect.

The point is that you can't rely on the compiler doing what you expect when there are multiple sequence points involved.

No, that's not right. The compiler must call weightMeasureCalibration(), perform a subtraction, and use that value as the argument to the Serial.print() method.

If currentLoad is a variable that cannot be accessed from outside the calling function, either directly or indirectly through a pointer, then (I'm not 100% sure on this) it may be implementation-defined whether it gets assigned the new value before or after the Serial.print() call. It ultimately doesn't matter if it's before or after Serial.print() because nothing (besides a debugger) can tell what its value is at either point in time. It certainly doesn't affect the observable results.