PIC mathematical operations weird problem
Where am I wrong with this calculation?


To add to the other answers, and to come at this from a different direction:

The PIC18F26K83 has a hardware multiplier, but no hardware divider, nor a floating-point unit. This means that any calculations involving division or non-integers will pull in library functions to do the maths in software. Compared to an equivalent calculation which avoids these things (if that's possible), this will increase the size of the program (unless the library functions are already used elsewhere) and make the calculation slower.

If space or time are important, then it's worth considering alternatives. In this instance we want to calculate:

adc_value*(4.9)*(11) / 4096 


For the top line, we can avoid losing precision by using tenths of a volt as the unit, rather than volts, giving us (with a little rearranging):

(adc_value * (10 * 4.9 * 11)) / 4096 


which is the same as:

(adc_value * 539) / 4096 


For the bottom line, we note that dividing by 4096 is the same as right-shifting by 12 (because 4096 = 2^12). This gives us:

(adc_value * 539) &gt;&gt; 12


(This will round down; if we want to round to the nearest integer, see below)

So now we have a calculation which avoids both non-integers and division.

Plugging in the values mentions in a comment to the question:

(1140 * 539) &gt;&gt; 12 = 150


150 in tenths of a volt = 15.0 V, which is the expected answer.

If we want the value in volts later, we can divide by 10 at that point - but not before. For internal calculations, it may be better to keep it in tenths of a volt to avoid losing any precision.



If we want to round to the nearest integer, the trick is to add to the top of the fraction half the value of the bottom of the fraction. In this case:

(x + 2048) &gt;&gt; 12


So if x is between 0 and 2047, this will output 0. If is x is between 2048 and (2047 + 4096), this will output 1. So the final calcuation is:

((adc_value * 539) + 2048) &gt;&gt; 12