Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C Arithmetic Different Output

Tags:

c

I'm getting different results when doing what I think is the same calculation. I imagine it's a type conversion issue.

I'm pulling a temperature value from a hardware sensor via I2C. The datasheet says the equation to do the conversion is as follows:

(((14_bit_ADC_value)/16382) * 165) - 40)

The two byte ADC value is stored in two chars and some shifting needs to occur to get the 14 bytes as such:

((((rawtemp[2] << 6 ) | (rawtemp[3] >> 2) / 16382) * 165) - 40);

The problem:

  • If I break up the operations it works.
  • If I combine them into one line it fails.

My Code is:

#include <stdio.h>
int main()
{
  char rawtemp[4];
  rawtemp[2] = 0x61; //example captured value
  rawtemp[3] = 0x40; //example captured value

  //method 1
  float test = 0;
  test = (rawtemp[2] << 6 ) | (rawtemp[3] >> 2);
  test = test / 16382;
  test = test * 165;
  test = test - 40;
  printf("test1: %f C\r\n", test);  //This works.

  //method 2
  test = (((rawtemp[2] << 6 ) | (rawtemp[3] >> 2) / 16382) * 165) - 40;
  printf("test2: %f C\r\n", test);  //This does not work.
  return 0;
}

Output:

$ ./k 
test1: 22.688316 C
test2: 1024280.000000 C

Why does the second method to derive the temperature value fail?

like image 900
Stateful Avatar asked Feb 11 '26 16:02

Stateful


1 Answers

There are two bugs in your method 2:

  1. (rawtemp[2] << 6 ) | (rawtemp[3] >> 2) / 16382 should be ((rawtemp[2] << 6 ) | (rawtemp[3] >> 2)) / 16382 , because the priority of bitwise OR is lower than divide.

  2. In C, if the two operands of '/' are both int, the result is also int, or floor(a/b), you can use (float)((rawtemp[2] << 6 ) | (rawtemp[3] >> 2)) / 16382 (or write 16382 as 16382.0) to convert one of the operand into float, then the result will also be int.

like image 110
bigeast Avatar answered Feb 14 '26 06:02

bigeast



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!