cpicxc8arithmetic-overflow

prevent arithmetic overflow


I want to calculate a voltage using ADC peripheral of PIC18F14K50. The result ranges between 0-1023 (10-bit). So I used this simple calculation:

uint16_t voltage = ADC_Result * 5000 / 1023;

However, the results are incorrect. I guess an arithmetic overflow happened. I tried many combination of parentheses, changing order of elements, etc.
The best result was 4088 when ADC_Result was 1023 using below code; which is really far from 5000.

uint16_t voltage = ADC_Result * (5000 / 1023);

What should I do to get better results in above calculation? Please don't suggest floating points as they cause disaster in MCUs! They use a lot of resources without any real benefit.


Solution

  • You could use a wider type for the intermediate multiplication, for example:

    uint16_t voltage = (uint32_t)ADC_Result * 5000 / 1023;
    

    EDIT

    If division by 1023 is too slow, you can get an approximately equal conversion by changing 5000 / 1023 to 5005 / 1024 which can use a fast bit shift for the division:

    uint16_t voltage = (uint32_t)ADC_Result * 5005 >> 10;
    

    N.B. 1023 * 5005 / 1024 ≃ 5000.1123