Форум программистов, компьютерный форум, киберфорум
C для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.63/510: Рейтинг темы: голосов - 510, средняя оценка - 4.63
Эксперт С++
 Аватар для Thinker
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5

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

13.10.2011, 18:41. Показов 107307. Ответов 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,980
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
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,312
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,980
22.04.2016, 15:17
Цитата Сообщение от Ferrari F1 Посмотреть сообщение
но зато алгоритм другой
Да и ветка - не С++, будьте внимательнее.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,312
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,875
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
Ответ Создать тему
Новые блоги и статьи
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701 Купил два термопринтера QR701. На сэлф-тесте написано: Language: PC936 (GB18030). Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
Создание формы заимствованного документа
Maks 03.08.2026
Задача: Необходимо создать собственную форму заимствованного документа. На форме должен быть реквизит "Покупатель", а также табличная часть со следующими реквизитами: - Расчетный счет покупателя. . .
Задача предоставления скидок покупателям
Maks 03.08.2026
Задача: В документе "Продажи" необходимо реализовать функционал предоставления скидок покупателям. Скидка должна автоматически рассчитываться и подставляться в соответствующее поле при выборе. . .
Почему SEO не начинается с ключевых слов: что проверить до написания текстов
Neotwalker 01.08.2026
Когда владельцу сайта предлагают заняться SEO, первым шагом часто становится сбор запросов и написание текстов. Логика кажется понятной: 1. Находим ключевые слова. 2. Добавляем их на. . .
Знание — сила: Доктрина интенциональности знаний, углубление в формулу
Hrethgir 01.08.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11957&stc=1&d=1785567302 Знаменитый афоризм Фрэнсиса Бэкона «Знание — сила» (Scientia potentia est) в массовой культуре принято понимать. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru