Как ускорить данный алгоритм?

226
04 апреля 2018, 10:38

Приветствую.

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

  for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); it++) {
    if (*it % 3 == 0) {
        std::cout << "bar" << std::endl;
    }
    if (*it % 5 == 0) {
        std::cout << "bazz" << std::endl;
    }
    if (*it % 5 == 0 && *it % 3 == 0) {
        std::cout << "barbazz" << std::endl;
    }
}

Есть ли у кого какие идеи по этому поводу? При необходимости могу привести код проверки на деление asm

Answer 1

Тут можно сделать таблицу результатов из заменить все ветвления на взятие остатка и индексирование:

constexpr char const * const table[15]
{
   "barbazz\n" //  0
,   ""         //  1
,   ""         //  2
,   "bar\n"    //  3
,   ""         //  4
,   "bazz\n"   //  5
,   "bar\n"    //  6
,   ""         //  7
,   ""         //  8
,   "bar\n"    //  9
,   "bazz\n"   // 10
,   ""         // 11
,   "bar\n"    // 12
,   ""         // 13
,   ""         // 14
};
for(auto it{vec.begin()}; it != vec.end(); ++it)
{
    std::cout << table[*it % 15];
}
Answer 2

Может, так?

const char* foo[] = { "","bar","bazz","barbazz"};
for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); it++)
{
    int idx = (*it % 3 == 0) + 2*(*it % 5 == 0);
    if (idx)
        std::cout << *it << " : " << foo[idx] << std::endl;
}
Answer 3

Вы решаете классическую fizbazz задачу.

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

Следующее - скорее всего в цепочке if Вы забили else и напутали порядок.

И последнее. В самое начало программы добавьте такое

ios_base::sync_with_stdio(false);

это отключит синхронизацию std-шник потоков и сишных.

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

Answer 4

Идея старая, я об этом знал еще в школе 40 лет назад: Числа делятся на 3, если сумма всех остатков от 10 делится на 3, а на 5 делится число, если остаток от 10 равен 5 или 0

READ ALSO
GTest и TearDown

GTest и TearDown

Когда происходит FAIL() тогда TearDown не освобождает ресурсы, можно ли как то сделать чтоб когда - происходит FAIL() происходил вызов деструктора...

293
Стили для QAction Qt5 C++

Стили для QAction Qt5 C++

Всем привет!

257
Как удалить значение из массива

Как удалить значение из массива

Дано: в массиве имеется user objectКаждый user имеет name и password

316
Получить id конференции

Получить id конференции

Пытаюсь получить id конференции, с которой был написан репортНо мне постоянно возвращает в тексте "1", для любой конференции

269