Эксперт С++
 Аватар для Thinker
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5

Самый быстрый алгоритм Евклида вычисления НОД

13.10.2011, 18:41. Показов 107369. Ответов 44
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Заинтересовал вопрос о различных реализациях алгоритма Евклида для неотрицательных целых чисел. Ниже привожу алгоритмы, собственноручно написанные, исходя из теоретического материала. Каждый алгоритм можно модифицировать в ту или иную сторону.

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

C
1
2
3
4
5
6
7
8
9
10
//обычный алгоритм Евклида через остатки
long Nod(long a, long b)
{
    while (a && b)
        if (a >= b)
           a %= b;
        else
           b %= a;
    return a | b;
}
C
1
2
3
4
5
6
7
8
9
10
// Алгоритм Евклида через разности
long Nod(long a, long b)
{
    while (a && b)
        if (a >= b)
           a -= b;
        else
           b -= a;
    return a | b;
}

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Бинарный алгоритм Евклида
long Nod(long a, long b)
{
    long deg = 0;
    if (a == 0 || b == 0)
        return a | b;
    while (((a | b) & 1) == 0)
    {
        deg++;
        a >>= 1;
        b >>= 1;
    }
    while (a && b)
    {
        if (b & 1)
            while ((a & 1) == 0)
                a >>= 1;
        else
            while ((b & 1) == 0)
                b >>= 1;
        if (a >= b)
            a = (a - b) >> 1;
        else
            b = (b - a) >> 1;
    }
    return ((a | b) << deg);
}
Еще один бинарный алгоритм, но он самый медленный из всех предыдущих.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
long Nod(long a, long b)
{
    long buf, deg = 0;
    if (a == 0 || b == 0)
        return a | b;
    while (((a | b) & 1) == 0)
    {
        deg++;
        a >>= 1;
        b >>= 1;
    }
    if (a)
        while ((a & 1) == 0)
            a >>= 1;
    while (b)
    {
        while ((b & 1) == 0)
            b >>= 1;
        if (a < b)
            b -= a;
        else
        {
            buf = a - b;
            a = b;
            b = buf;
        }
        b >>= 1;
    }
    return (a << deg);
}
20
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
13.10.2011, 18:41
Ответы с готовыми решениями:

Найти НОД для одномерного массива, используя алгоритм Евклида
Вопрос в том как найти НОД для одномерного массива, используя алгоритм Евклида?

Найти НОД двух целых положительных чисел А и В, используя алгоритм Евклида
Описать функцию NOD2(A,B) целого типа,находящую наибольший общий делитель(НОД) двух целых положительных чисел А и В,используя алгоритм...

Алгоритм Евклида для вычисления НОД
Алгоритм Евклида для вычисления наибольшего общего делителя двух натуральных чисел, формулируется так: нужно заменять большее число на...

44
 Аватар для evgr
117 / 33 / 14
Регистрация: 13.02.2015
Сообщений: 795
05.03.2015, 06:20
Студворк — интернет-сервис помощи студентам
GREGOR_812, для этого в библиотеке time.h есть функции
C
1
2
time_t time(time_t *time);
clock_t clock(void);
Однако имейте ввиду, что рекурсивные алгоритмы, как правило, не отличаются высокой скоростью работы.
0
835 / 643 / 101
Регистрация: 20.08.2013
Сообщений: 2,524
05.03.2015, 10:39
Цитата Сообщение от evgr Посмотреть сообщение
Однако имейте ввиду, что рекурсивные алгоритмы, как правило, не отличаются высокой скоростью работы.
Если компилятор не решит развернуть рекурсию?)
0
 Аватар для evgr
117 / 33 / 14
Регистрация: 13.02.2015
Сообщений: 795
05.03.2015, 10:47
Цитата Сообщение от Qwertiy Посмотреть сообщение
решит развернуть рекурсию
Ну тогда алгоритм несомненно перестанет быть рекурсивным. А вообще зачем писать код с рекурсией и надеяться на компилятор, если можно сразу создать алгоритм без использования рекурсии?
0
28 / 28 / 5
Регистрация: 23.04.2014
Сообщений: 130
05.03.2015, 16:20
evgr,

Не по теме:

ко мне можно на ты


Спасибо, попробую сегодня вечерком протестить на разных числах
0
 Аватар для castorsky
1978 / 1082 / 87
Регистрация: 29.11.2013
Сообщений: 3,353
05.03.2015, 18:14
Цитата Сообщение от evgr Посмотреть сообщение
Ну тогда алгоритм несомненно перестанет быть рекурсивным
алгоритм не может быть сначала рекурсивным, а после компиляции исходников стать не рекурсивным.
Цитата Сообщение от evgr Посмотреть сообщение
А вообще зачем писать код с рекурсией и надеяться на компилятор, если можно сразу создать алгоритм без использования рекурсии?
Надо понимать что говорите. А говорите Вы откровенную, простите, чушь. Итерация - частный случай рекурсии, если что. Оптимизация рекурсии явление не новое и если компилятор этого не умеет, то стоит задуматься о целесообразности его использования.
0
 Аватар для evgr
117 / 33 / 14
Регистрация: 13.02.2015
Сообщений: 795
06.03.2015, 08:45
castorsky, а ещё было бы неплохо понимать, что вы пишите. А пишите вы, судя по всему, как Бог на душу положит. "Ааа, зачем мне вообще нужна оптимизация? Компилятор же всё сам за меня сделает!" - думаете вы. А потом, что дизассемблируете ваш экзешник и смотрите, действительно ли компилятор всё оптимизировал? Даже если так, оно вам надо? Не проще сразу писать нормальный код, чем приобретать себе лишнюю головную боль?
0
 Аватар для castorsky
1978 / 1082 / 87
Регистрация: 29.11.2013
Сообщений: 3,353
06.03.2015, 10:36
Цитата Сообщение от evgr Посмотреть сообщение
а ещё было бы неплохо понимать, что вы пишите
я все прекрасно понимаю, и Вам пытаюсь донести. Вот Вам рекурсивный алгоритм
https://www.cyberforum.ru/cgi-bin/latex.cgi?f \left( x \right) = \left\{\begin{matrix}0, x = 0\\ g \left(f, x \right), x < 0 \\ h \left(f, x \right), x > 0\end{matrix}\right.
реализуйте на своё усмотрение, или как рекурсию, или как частный случай рекурсии - итерацию. Как Вам будет угодно.
Цитата Сообщение от evgr Посмотреть сообщение
А пишите вы, судя по всему, как Бог на душу положит. "Ааа, зачем мне вообще нужна оптимизация? Компилятор же всё сам за меня сделает!" - думаете вы.
Я думаю что оптимизация - это не писать функции простыни больше 20-25 строк форматированного кода. В таком случае просто не влезет столько данных чтобы компилятор не справился с оптимизацией рекурсии в цикл.
Цитата Сообщение от evgr Посмотреть сообщение
Не проще сразу писать нормальный код
Боюсь что Вы только на пороге к понимаю этих слов.
0
 Аватар для evgr
117 / 33 / 14
Регистрация: 13.02.2015
Сообщений: 795
06.03.2015, 11:09
Цитата Сообщение от castorsky Посмотреть сообщение
Вот Вам рекурсивный алгоритм
Да вы пытаетесь меня втянуть в какую-то специальную олимпиаду! Смотрите, как бы вас кто-нибудь также не развёл на слабо и не заставил сделать за него что-нибудь
Давайте-ка свернём эту дискуссию, если вы не против?
0
 Аватар для castorsky
1978 / 1082 / 87
Регистрация: 29.11.2013
Сообщений: 3,353
06.03.2015, 11:25

Не по теме:

Простейшие основы матана для Вас оленьпиада? Тут надо курить матчасть. Я указал Вам на ошибку, как человек рациональный Вы долны поразмыслить на сказанным.


Цитата Сообщение от evgr Посмотреть сообщение
Давайте-ка свернём эту дискуссию, если вы не против?
ЧТД.

Добавлено через 1 минуту
evgr, под "реализуйте на своё усмотрение" я понимаю не "реализуйте" а "можете реализовать как Вам вздумается", т.е. это не попытка взять на слабо, а просто пример.
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,981
06.03.2015, 11:44
evgr, очень хорошее предложение!
И вообще, друзья, старайтесь поменьше эмоций проявлять, и с оценками собеседников поаккуратнее...
1
06.03.2015, 12:44

Не по теме:

А по поводу оптимизации рекурсии почитать можно что-нибудь? Авторы, названия книг интересуют

0
 Аватар для castorsky
1978 / 1082 / 87
Регистрация: 29.11.2013
Сообщений: 3,353
06.03.2015, 13:01
начните с вики
0
807 / 534 / 158
Регистрация: 27.01.2015
Сообщений: 3,017
Записей в блоге: 1
21.04.2016, 23:50
C++
1
2
3
4
unsigned long long a(34), b(27); // а должно быть больше b
while (a % b)
  swap(a %= b, b);
cout << b << endl;
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13212 / 6845 / 1825
Регистрация: 18.10.2014
Сообщений: 17,327
22.04.2016, 03:28
Цитата Сообщение от diagon Посмотреть сообщение
Такой тоже должен быстро работать
C
1
2
3
4
5
int gcd( int a, int b )
{
  while( b^=a^=b^=a%=b );
  return a;
}
Правда оптимизирующие компиляторы его преимущества на нет сводят...
Такой вариант, во-первых, некорректен, ибо содержит неупорядоченные (unsequenced) множественные модификации одной и той же переменной. Поведение этого кода не определено.

Во-вторых, такой вариант построен на предположении, что цепочка xor является наиболее эффективным способом обмена двух целочисленных переменных, что также не верно.
0
807 / 534 / 158
Регистрация: 27.01.2015
Сообщений: 3,017
Записей в блоге: 1
22.04.2016, 12:50
Программка медленнее, но зато алгоритм другой. Все зависит от кол-ва простых чисел в векторе.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <vector>
#include <cmath>
#include <windows.h>
 
using namespace std;
 
vector<unsigned> getDividers(unsigned value)
{
    static vector<unsigned> numbers =
    {
        2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
        43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97
    };
    vector<unsigned> temp(numbers[numbers.size() - 1]);
    int i(0);
    for (; value / numbers[i];)
        if (!(value % numbers[i]))
            value /= numbers[i], ++temp[numbers[i]];
        else
            ++i;
    temp.erase(temp.begin() + numbers[i] + 1, temp.end());
    return temp;
}
 
unsigned findGCD(const vector<unsigned>& value1,
    const vector<unsigned>& value2)
{
    unsigned gcd(1), count(min(value1.size(), value2.size()));
    for (unsigned i(2); i < count; i++)
        if (value1[i] && value2[i])
            gcd *= static_cast<unsigned>(pow(i, min(value1[i], value2[i])));
    return gcd;
}
 
int main(void)
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    unsigned a(1260), b(245);
    vector<vector<unsigned>> dividers =
    {
        getDividers(a), getDividers(b)
    };
    cout << findGCD(dividers[0], dividers[1]) << endl;
    system("pause");
    return 0;
}
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,981
22.04.2016, 15:17
Цитата Сообщение от Ferrari F1 Посмотреть сообщение
но зато алгоритм другой
Да и ветка - не С++, будьте внимательнее.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13212 / 6845 / 1825
Регистрация: 18.10.2014
Сообщений: 17,327
22.04.2016, 20:42
Цитата Сообщение от Ferrari F1 Посмотреть сообщение
Программка медленнее, но зато алгоритм другой. Все зависит от кол-ва простых чисел в векторе.
О, да, разумеется, зависит! Программа просто тупо вылетает за размер вектора и падает, если ни одно из чисел в векторе не делит входное число. Как это должно вообще работать в финальном варианте? Вы предлагаете заранее заполнить вектор простыми числами вплоть до корня из UINT_MAX?
0
807 / 534 / 158
Регистрация: 27.01.2015
Сообщений: 3,017
Записей в блоге: 1
22.04.2016, 21:00
TheCalligrapher, главное - продемонстрировать другой подход к решению задачи!
код писался ради идеи, а не для рабочего пользования.
а простые числа можно, например, запихнуть в файл. Своеобразная бд простых чисел получится.
0
Модератор
Эксперт по электронике
8982 / 6749 / 921
Регистрация: 14.02.2011
Сообщений: 23,876
22.04.2016, 22:01
Цитата Сообщение от Ferrari F1 Посмотреть сообщение
а простые числа можно, например, запихнуть в файл.
и что это быстро?
Цитата Сообщение от Ferrari F1 Посмотреть сообщение
главное - продемонстрировать другой подход к решению задачи!
я тут вижу тупой перебор
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
заполнить вектор простыми числами вплоть до корня из UINT_MAX?
а если числа будут хотя бы 64 бита, я уж не говорю о большем размере, какой будет размер файла?
0
0 / 0 / 0
Регистрация: 29.09.2016
Сообщений: 8
08.12.2016, 19:18
C++
1
2
3
int euclidean(int a, int b) {
    return b == 0 ? a : euclidean(b, a % b);
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
08.12.2016, 19:18

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

Построить алгоритм Маркова, который ищет НОД (Алгоритм Евклида)
Здравствуйте, ребята, выручайте. Весь инет перерыл, всю голову сломал, но не могу сделать. Суть в чем, надо построить алгорифм Маркова,...

НОД . Рекурсивный алгоритм Евклида
1. Даны два натуральных числа X и Y. Найти их наибольший общий делитель, используя рекурсивный алгоритм Эвклида. Вход: В текстовом...

Алгоритм Евклида для нахождения НОД
Уважаемые форумчане, никак не получается написать алгоритм Евклида, возможно не хватает знаний, возможно опыта. Сам алгоритм я знаю, но как...

НОД двух чисел алгоритм Евклида
Найти найбольший общий делитель двух чисел по алгоритму Евклида. Использовать рекурсию.


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Опции темы

Новые блоги и статьи
Жизня: рисунок укладки багажа, сделанный клодом
anaschu 21.08.2026
Сделал 15 снимков, он по снимкам сделал схему.
Был там один разговор по поводу свободы в материальном мире.
kumehtar 19.08.2026
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства. Жизнь действительно предъявляет каждому. . .
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
Лето уходит
kumehtar 17.08.2026
Мысли в слух
kumehtar 17.08.2026
Забавно, насколько сейчас стала доступна информация. Например о магии, духовном развитии, медитациях, и других подобных направлениях, ранее зачастую тайных, передаваемых от учителя к ученику. Хотя. . .
Перемещение строк из ТЧ в другой документ с учетом текущего пробега
Maks 17.08.2026
Реализация из решения ниже выполнена на примере нетипового документа "Автозапчасти", с ТЧ "Шины". За основу взят алгоритм отсюда: https:/ / www. cyberforum. ru/ blogs/ 359708/ 10838. html Задача: . . .
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru