2015-08-27 3 views
0

я получил некоторые данные из этой таблицы: enter image description hereИспользуя цикл из значения диапазона

это может быть использование помощи (для цикла)?

Недавно я использовал (если еще) функцию, но это кажется слишком длинным.

Я новичок в программировании на С. Вот код (если еще) функция, что я сделал:

 if (0 < result < 409 ) // 0 to 408 
     { 
      volt = 0 ; 
     } 
     else if (409 < result < 818) //408 to 817 
     { 
      volt = 1 ; 
     } 
     else if (818 < result < 1227) //818 to 1226 
     { 
      volt = 2 ; 
     } 
     else if (1227 < result < 1636) //1227 to 1635 
     { 
      volt = 3 ; 
     } 
     else if (1636 < result < 2045) // 1636 to 2044 
     { 
      volt = 4 ; 
     } 
     else if (2045 < result < 2454) // 2045 to 2453 
     { 
      volt = 5 ; 
     } 
     else if (2454 < result < 2863) //2454 to 2862 
     { 
      volt = 6 ; 
     } 
     else if (3271 < result < 2863) //2863 to 3271 
     { 
      volt = 7 ; 
     } 
     else if (3860 < result < 3272) //3272 to 3860 
     { 
      volt = 8 ; 
     } 
     else if (4094 < result < 3861) //3861 to 4094 
     { 
      volt = 9 ; 
     } 

     else if (result >= 4095) //4095++ 
     { 
      volt = 10 ; 
     } 
+1

Как насчет чтения хорошей C книги? Это покажет вам все, что вам нужно, чтобы решить это самостоятельно. – Olaf

+0

Хорошо исправить ошибки компиляции перед публикацией здесь –

ответ

1

Для начала 409 < result < 818 не выражение, которое делает то, что вы думаете, он делает в C. Это может иметь смысл математически, но C нуждается в вас, чтобы быть немного более конкретно:

(409 < result) && (result < 818) 

Объясняя далее, выражение 409 < result < 818 будет первым работать значение истинности для 409 < result, давая ноль или один, который мы будем называть X , Затем результат будет передан в X < 818, чтобы дать новое значение истины.

Таким образом, в этом случае, вы всегда будете получать истинное просто потому, что X нуля или одного является всегда меньше 818. Следующая программа демонстрирует это в действии:

#include <stdio.h> 

void Between400And600 (int n) { 
    printf ("%d between 400 and 600? Old = %d, new = %d\n", 
     n, 
     400 < n < 600, 
     (400 < n) && (n < 600)); 
} 

int main (void) { 
    Between400And600 (111); 
    Between400And600 (555); 
    Between400And600 (999); 
    return 0; 
} 

первый результат на каждой линии оригинал один, old. Во-вторых, мое рекомендуемое исправление, new. Как вы можете видеть, все ваши выражения дают 1 (истина), в то время как исправление только дает истинное для значения между пределами:

111 between 400 and 600? Old = 1, new = 0 
555 between 400 and 600? Old = 1, new = 1 
999 between 400 and 600? Old = 1, new = 0 

Кроме того, некоторые из ваших проверок диапазонвыхода с номерами, находящимися в неправильном порядке. Кроме возможности некоторого более высокого порядка по математике я не в курсе, ни один номер не может быть больше, чем 3860 и менее 3272 в то же время:

И, сверх того, исключительное использование <, а не <= означает, что вы отсутствует некоторые случаи, например, когда result является 409.

Если вы только после того, как сжатый способа сделать отображение, я выбрал бы что-то вроде:

unsigned int getVolt (unsigned int adc) { 
    if (adc < 409) return 0; 
    if (adc < 818) return 1; 
    if (adc < 1227) return 2; 
    if (adc < 1636) return 3; 
    if (adc < 2045) return 4; 
    if (adc < 2454) return 5; 
    if (adc < 2863) return 6; 
    if (adc < 3272) return 7; 
    if (adc < 3681) return 8; 
    if (adc < 4095) return 9; 
    return 10; 
} 

и назвать его просто с:

volt = getVolt (result); 

Это много короче , намного яснее и, следовательно, намного меньше подвержены ошибкам.

Учитывая, что все, кроме последнего кратна 409, вы могли бы сократить его еще больше, что-то вроде:

unsigned int getVolt (unsigned int adc) { 
    if (adc < 4090) return adc/409; 
    if (adc < 4095) return 9; 
    return 10; 
} 

но вы теряете ясность (и гибкость, должны изменить пороги) в этом случае я бы, наверное, придерживался своей первой реализации, учитывая, что это не тоже большой. Конечно, если бы это закончилось пятьюдесятью if заявлениями, я бы, вероятно, искал лучшее решение, но десять строк кода не так уж плохи.


Если вы хотите сохранить код относительно короткий пока еще позволяют значительно увеличить число проверок, вы могли бы сделать его управлялся таблицей нечто похожее на:

unsigned int getVolt (unsigned int adc) { 
    const static unsigned thresholds[] = { 
     409, 818, 1227, 1636, 2045, 2454, 2863, 3272, 3681, 4095, 
     // as many entries as you need. 
    }; 
    const static int sz = sizeof(thresholds)/sizeof(*thresholds); 

    for (int idx = 0; idx < sz; idx++) 
     if (adc < thresholds[idx]) 
      return idx; 

    return sz; 
} 

То есть ограничение, возвращаемые значения должны начинаться с нуля (то же самое, что и индекс, 0..9 плюс значение по умолчанию 10), но это нормально для вашего конкретного случая.

+0

могу ли я знать, '0

+0

@NazifJaafar: Немногие языки программирования поддерживают сравнение trinary. C ни один из них. Вы должны разделить это на два сравнения sepearte. Пожалуйста, прочитайте книгу или учебник. Не обижайтесь, но вам не хватает элементарных знаний, поэтому, пожалуйста, научитесь ходить, прежде чем начинать бежать. – Olaf

+0

@ NazifJaafar, добавил еще несколько объяснений ответа. – paxdiablo

0

Ditto на первой части, что сказал paxdiablo, но ответить на ваш вопрос, вы могли поместить это в цикл, но если вы посмотрите на ваши номера, диапазон чисел в каждом if/else if блока код тот же; 409. Затем внутри этого блока вы устанавливаете вольт = номер раздела, в котором вы находитесь. В первом разделе вы устанавливаете вольт = 0, во втором - вольт = 1 и т. Д. Поскольку диапазон в каждом разделе увеличивается на 409 каждый раз, вы можете просто заменить все, что вы написали, volt = result/409.

Помните, что (при условии, что результат является целым числом), c-язык будет обрабатывать result/409 с использованием целочисленного деления. Итак, если результат равен> = 0 и < 409, результат/409 с равным 0. Если результат равен> = 409 и < 818, тогда результат/409 будет равен 1 и так далее. Это, однако, означает, что если результат = 4094, вольт будет равен 9, что не соответствует вашему графику, но может быть тем, что вы хотите.

Если вам нужно сделать что-то подобное (с постоянно увеличивающимися диапазонами), то вы, вероятно, захотите использовать цикл for. Цикл for также должен быть быстрее (я думаю). Вы должны были бы использовать снова тот факт, что ваши диапазоны идут вверх постоянным шагом 409, и таким образом сделать что-то вроде

for (int i = 0; i < max; i++) 
{ 
    int lowerBound = (result/i); 
    int upperBound = (result/i + 408); 
    //or something 
    //...other necessary code here... 
} 
+1

Хороший звонок, хотя я думаю, что это должно быть '409', а не' 408'. Последнее значение '4095' также является особым случаем, так как порог« кратное 409 »будет« 4090 ». – paxdiablo

+0

Упс, да. Пропустил это, спасибо. –

0

Это просто 12-бита (4096-счета) АЦПА, с полным - масштабный вход 10 В. Он является линейным по этой шкале, так что ни одна таблица или цикл не является необходимым:

#define ADC_BITS  12 
#define ADC_MIN_VOLTS 0 
#define ADC_MAX_VOLTS 10 

#define ADC_COUNTS  (1 << ADC_BITS) 
#define ADC_VRANGE  (ADC_MAX_VOLTS - ADC_MIN_VOLTS) 


double adc_counts_to_volts(int counts) 
{ 
    return counts * (double)ADC_VRANGE/ADC_COUNTS; 
} 

Вы можете заменить это целочисленной версии, чтобы дать целое вывод:

int adc_counts_to_volts(int counts) 
{ 
    return counts * ADC_VRANGE/ADC_COUNTS; 
} 
+0

Остерегайтесь в верхнем конце этого диапазона, это не * довольно * линейно. – paxdiablo

+0

@paxdiablo Хм, хороший звонок - я только пробовал пару очков. Возможно, в таблице данных больше информации о нелинейности этого устройства. –

Смежные вопросы