Оптимизировать несколько условий сравнения - PullRequest
2 голосов
/ 13 февраля 2020

Мой основной код должен сравнивать целочисленную команду ASCII, и мне интересно, есть ли решение для ее оптимизации.

Я могу послать от '1' до '128' на последовательной шине и достичь правильный объект, вот как я это делаю:

// this is how I deal with the data sent on the serial bus 
int translateASCII(char requestBuffer[10]){
    char word[4] = {0};
    word[0] = (int)requestBuffer[0];
    word[1] = (int)requestBuffer[1];
    word[2] = (int)requestBuffer[2];
    int n = atoi(word);
    return n;
}

void interpreteASCII(int ascii){
    if (ascii > 0 && ascii < 33){
        if (ascii < 9){
            blabla
        }
        else if (ascii < 17){
            blabla
        }
        else if (ascii < 25){
            blabla
        }
        else
            blabla
    }
    else if (ascii < 65){
        if (ascii < 41){
            blabla
        }
        else if { ... }
    }            
}

Так что я ищу способ оптимизировать эту «архитектуру». Также задумывался о функции переключения регистра, но, похоже, она сравнивает мою переменную ASCII только с одним целым числом, например:

switch (ascii){
     case '8':
         blabla

, и это не то, что я ищу, потому что инструкции действительно зависят от переменной ASCII который сортируется по интервалам 32, которые сами должны быть отсортированы по интервалам 8 значений.

Ответы [ 3 ]

3 голосов
/ 13 февраля 2020

Вы говорите, что вам нужен один случай для каждого интервала 8, например, 1-8, 9-16 и т. Д. c. Попробуйте это:

switch ((ascii + 7)/ 8) {
case 0: // input was zero
    break;
case 1: // input was in [1..8]
    break;
// ...
case 8: // input was in [57..64]
    break;
}
2 голосов
/ 13 февраля 2020

Прежде всего, избавьтесь от int и замените его на char или uint8_t. Кажется маловероятным, что у вас есть таблица символов с отрицательными индексами.

Далее, вы в основном проверяете, находится ли что-то в определенных интервалах. Наименее неэффективный способ сделать это с помощью if-else - это сделать это в порядке возрастания:

if(ascii < 17)
  ...
else if(ascii < 25)
  ...
else if(ascii < 33)
  ...

Очевидно, что "числа волхвов c" следует заменить константами или символьными литералами.

Если есть интервалы 8 (это , а не то, что дают ваши маги c числа), вы можете улучшить производительность, выполнив ascii / 8 в качестве поиска. Либо с помощью простого переключателя, либо, возможно, с помощью поиска указателя на функцию. Пример последнего:

#include <stdio.h>
#include <stdint.h>

void f0_7   (uint8_t n) { printf("%d %s\n", n, __func__); }
void f8_15  (uint8_t n) { printf("%d %s\n", n, __func__); }
void f16_23 (uint8_t n) { printf("%d %s\n", n, __func__); }
... // up to 127

void interpreteASCII(uint8_t ascii)
{
  typedef void(lookup_func)(uint8_t);
  lookup_func* const LOOKUP[] = { f0_7, f8_15, f16_23, ... /* up to 127 */ };

  LOOKUP[ascii/8](ascii);
}

int main (void)
{
  for(uint8_t i=0; i<24; i++)
  {
    interpreteASCII(i);
  }

  return 0;
}

(хотя некоторая проверка границ перед вызовом такого поиска в таблице не является плохой идеей.)

0 голосов
/ 21 февраля 2020

Непонятно, что вы подразумеваете под «оптимизировать».

  • Хотите, чтобы он занимал как можно меньший объем памяти? Тогда ответ Джона Цвинка (или что-то в этом роде), вероятно, является лучшим выбором.

  • Хотите, чтобы он работал максимально быстро? Тогда наилучшим подходом будет таблица поиска, состоящая из 128 записей (многие из которых содержат одинаковое значение).

  • Вы хотите, чтобы его было как можно проще читать и понимать? Тогда ничто, вероятно, не сравнится с решением, которое вы уже придумали.

...