2016-08-29 2 views
4

В C++, какое из следующих решений более надежное и надежное для подсчета от 0 до 99 и сохранение каждой итерации в переменных для десятков и одних мест? И как можно улучшить любой метод, чтобы сделать его максимально быстрым и ресурсоемким?Подсчет от 0 до 99

typedef int (*IntFunction) (int* _SegmentList); 

int display1SegmentPinNums[] = {...pin numbers...}; 
int display2SegmentPinNums[] = {...other pin numbers...}; 

// Then I have some functions that display a number to 7-segment displays. They each return an integer 1 and have a parameter of (int* _SegmentList), as per the type definition above 

// An array of all the functions 
IntFunction displayFunctions[10] = {display_0, display_1, display_2, display_3, display_4, display_5, display_6, display_7, display_8, display_9}; 

// Solution 1 
for (int tens = 0; tens < 10; tens++) 
{ 
    for (int ones = 0; ones < 10; ones++) 
    { 
     displayFunctions[tens](display1SegmentPinNums); 
     displayFunctions[ones](display2SegmentPinNums); 
    } 
} 

// Solution 2 
for (int i = 0; i < 100; i++) 
{ 
    ones = (i % 10); 
    tens = ((i - ones)/10); 

    displayFunctions[tens](display1SegmentPinNums); 
    displayFunctions[ones](display2SegmentPinNums); 
} 

Edit: Я включил несколько упрощенный вариант моего полного кода. Надеюсь, это поможет лучше ответить. Это для проекта Arduino BTW, с 7-сегментными дисплеями и попыткой сделать секундомер.

+1

В чем проблема? Сколько раз десятки приращений и сколько раз они увеличиваются? Если это так, то математика не нужна. – NathanOliver

+1

* «И как можно улучшить любой метод, чтобы сделать его максимально быстрым и ресурсоемким?» * Ваша учебная книга с 80-х годов? –

+1

Какая проблема, с которой вы решили решиться? Я сомневаюсь, что это узкое место в вашем коде. – CoryKramer

ответ

5

Любой достойный оптимизирующий компилятор должен прийти к результату, чтобы tens и ones содержали 9 в конце, основываясь на постоянном распространении, разворачивании цикла и устранении мертвого кода.

Теперь в зависимости от вашего реального тела цикла, и не принимая во внимание умных оптимизаций компилятора, вы можете анализировать код, counting type of operations:

  • Решение 1: 11 инициализацию, 121 сравнения, 110 с шагом, 200 Назначения
  • Раствор 2: 1 инициализация, 101 сравнения, 100 приращения, 200, 200 заданий разделяющих операций (modulo и деление), 100 вычитаний

Тогда это зависит от процессора ара архитектуры и других факторов:

  • Если гипотетически все операции потребуют одного гипотетического цикла ЦП, решение 1 явно выиграет.
  • Но на самом деле это намного сложнее, принимая во внимание оптимизацию оборудования, такую ​​как кеширование, предсказание ветвей и т. Д., А также стоимость модуляции и деления. Таким образом, лучший способ, безусловно, будет измеряться с помощью некоторого кода бенчмаркинга.

Edit: о коде изменения

Если функции выполняют некоторые побочные эффекты (отображение и т.д.), то, конечно, ваше тело цикла не будет оптимизирован прочь. Остающийся комментарий, который я сделал, остается верным, потому что решение 1 и решение 2 оба вызова дополнительных функций одинаковое количество раз с теми же параметрами.

+0

Не учитывайте оптимизацию компилятора и общую 32 КБ ОЗУ для компьютера, о котором вы бы посоветовали? –

+0

@ ZodiacZubeda интуитивно я бы пошел на решение 1 (см. Ссылку позади «modulo» в моем ответе). Не все операторы равны по сложности, а модуляция и деление обычно сложнее, особенно на низкодоходном процессоре. Но это интуиция: только bechnmarking может дать вам определенный ответ. – Christophe

0

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

Также второе решение в соответствии с вашими требованиями к ОЗУ является лучшим, поскольку оно использует только 3 переменные, а не 4 как первый.

Но эта четвертая переменная j, может быть только несколько байт (в зависимости от платформы), но, как правило 4.

Во всяком случае, если вы хотите сохранить все «десятки» и «те», вам нужно список или вектор.

Для лучшего, более конкретного ответа, пожалуйста, разместите большую проблему с картинкой, с которой вы сталкиваетесь!

+0

Пожалуйста, объясните голосу! – Paul

+2

Не downvoter, но: Давайте будем честными, на X86-64 нет никакого разлива реестров для этих 4 переменных. – JustSid

2

Решение 1 требует меньше вычислений, просто добавление, в то время как решение 2 требует целых операций деления и модуля в каждой итерации.

С другой стороны, для решения 1 требуется дополнительная переменная, которая может привести к увеличению использования памяти. Но это зависит от вашего оборудования и от оптимизации вашего компилятора.

1

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

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

Например, если вы решите, что для вас надежность заключается в том, что подсчет не может быть прерван или изменен другим приложением, запущенным на вашей машине arduino. Затем вы должны добавить контрмеры в свой код, чтобы уменьшить этот риск, и проверить, как ваша программа реагирует на ситуацию такого типа. Одним из способов измерения счетчика может быть, например, получить эксклюзивный доступ к ресурсу, пока он не завершит подсчет. И, как вы можете догадаться, это ухудшит скорость использования ресурсов вашего ресурса &.

Поэтому я бы сказал, что довольно сложно ответить на ваш вопрос в текущем состоянии. Надеюсь, мне все же удалось дать вам некоторые идеи для дальнейшего продвижения.

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