yogii
yogii

Reputation: 88

Receiving a long value of an operation using two integers (GNU C)

Using Microchip C Compiler (based on Gnu C Compiler), I need to process two integer values and return an integer value. Integers are 16 bit wide, longs are 32 bit.

During the calculation, the range of 16bit will be exceeded. This is what I have done so far:

unsigned int calcVoltage(unsigned int adcValue){
    long voltage = ((long)adcValue * (long)VOLTAGE) / (long)ADCRANGE;
    return voltage; //12-bit ADC-Value, 3000mv max
}

VOLTAGE is a constant, assigned to 3000 at the moment. Multiplying adcValue (0 to 12bit) by 3000 will exceed 16bit. In the end, the result of multiplication will be divided by 4095, so that the result is going to be below 16bit again.

IMO, my code is quite ugly, as I do not know how to do it better. How can I ensure, that the compiler uses 32bit long integers during the calculation without all the explicit casting?

Upvotes: 0

Views: 273

Answers (1)

Jonathan Leffler
Jonathan Leffler

Reputation: 753665

If you define VOLTAGE correctly, the rest falls into place because of the usual conversion rules.

#define VOLTAGE 3000L

long voltage = (adcValue * VOLTAGE) / ADCRANGE;

That's all it takes.

Why, you ask? Because when the compiler works out how to process the multiplication, it has to multiply a long (VOLTAGE) by an int (adcValue), and the way it must do that is by promoting the int to a long, yielding a long result. When it now evaluates the division, it has a long on the LHS (dividend) and an int on the RHS (divisor) so it must convert the int to a long again, do the computation as a long, yielding a long. It must then process the assignment. The LHS is a long; the expression on the RHS is a long; the world is a happy place (and the code is clean and castless).

Upvotes: 3

Related Questions