2015-11-08 2 views
3

Я получаю разные результаты при выполнении того, что, по моему мнению, является одним и тем же вычислением. Я предполагаю, что это проблема преобразования типов.C Арифметический разный вывод

Я вытягиваю значение температуры от hardware sensor via I2C. datasheet говорит уравнение для выполнения преобразования заключается в следующем:

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

значение АЦП два байта хранится в двух символов, а некоторые смещение должно произойти, чтобы получить 14 байт как таковой:

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

проблема:

  • Если я нарушу эти операции она работает.
  • Если я объединю их в одну строку, это не удастся.

Мой код:

#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; 
} 

Выход:

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

Почему второй способ вывести значение температуры не получится?

+3

Просто догадка, кто-то, вероятно, может дать лучший ответ и доказать это, но, возможно деление имеет преимущество по побитовому ИЛИ? Попробуйте добавить круглые скобки. ** РЕДАКТИРОВАТЬ **: см. Ниже комментарий (и). – Arc676

+3

'/' является перегруженным оператором, поведение которого сильно отличается в зависимости от того, есть ли у вас целые числа или операнды с плавающей запятой. Убедитесь, что это не проблема. –

+0

@UlrichEckhardt «перегруженный оператор» на языке программирования ** C **! Слово «перегрузка» не используется нигде в индексе K & R. – Jameson

ответ

2

Так правильно method2 является:

test = ((((rawtemp[2] << 6) | (rawtemp[3] >> 2))/16382.0) * 165) - 40; 
+0

Святое дерьмо, ответ другой, если это 16382 против 16382.0! – Stateful

+0

Не совсем святое дерьмо, но язык С. – dlask

+1

он заставляет/оператор обрабатывать числа как поплавки ... –

4

Есть две ошибки в методе 2:

  1. (rawtemp[2] << 6) | (rawtemp[3] >> 2)/16382 должен быть ((rawtemp[2] << 6) | (rawtemp[3] >> 2))/16382, поскольку приоритет побитового OR ниже водораздела.

  2. В C, если оба операнда '/' оба INT, результат также INT или floor(a/b), вы можете использовать (float)((rawtemp[2] << 6) | (rawtemp[3] >> 2))/16382 (или писать 16382, как 16382.0), чтобы преобразовать один из операндов в поплавок, то результат также будет int.

0

Другой способ сделать приведение типа выражения (rawtemp[2] << 6) | (rawtemp[3] >> 2) плавать как в

//method 2 
test = ((((float) ((rawtemp[2] << 6) | (rawtemp[3] >> 2)))/16382) * 165) - 40; 
Смежные вопросы