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

Узнай цену своей работы

Формулировка задачи:

Заинтересовал вопрос о различных реализациях алгоритма Евклида для неотрицательных целых чисел. Ниже привожу алгоритмы, собственноручно написанные, исходя из теоретического материала. Каждый алгоритм можно модифицировать в ту или иную сторону. Считается, что бинарный алгоритм работает быстрее, но мои тесты показывают, что два первых алгоритма работают быстрее бинарного. Может ли кто перепроверить на скорость на своих компиляторах, а то очень интересно и не видится никаких преимуществ бинарного алгоритма.
Листинг программы
  1. //обычный алгоритм Евклида через остатки
  2. long Nod(long a, long b)
  3. {
  4. while (a && b)
  5. if (a >= b)
  6. a %= b;
  7. else
  8. b %= a;
  9. return a | b;
  10. }
Листинг программы
  1. // Алгоритм Евклида через разности
  2. long Nod(long a, long b)
  3. {
  4. while (a && b)
  5. if (a >= b)
  6. a -= b;
  7. else
  8. b -= a;
  9. return a | b;
  10. }
Листинг программы
  1. // Бинарный алгоритм Евклида
  2. long Nod(long a, long b)
  3. {
  4. long deg = 0;
  5. if (a == 0 || b == 0)
  6. return a | b;
  7. while (((a | b) & 1) == 0)
  8. {
  9. deg++;
  10. a >>= 1;
  11. b >>= 1;
  12. }
  13. while (a && b)
  14. {
  15. if (b & 1)
  16. while ((a & 1) == 0)
  17. a >>= 1;
  18. else
  19. while ((b & 1) == 0)
  20. b >>= 1;
  21. if (a >= b)
  22. a = (a - b) >> 1;
  23. else
  24. b = (b - a) >> 1;
  25. }
  26. return ((a | b) << deg);
  27. }
Еще один бинарный алгоритм, но он самый медленный из всех предыдущих.
Листинг программы
  1. long Nod(long a, long b)
  2. {
  3. long buf, deg = 0;
  4. if (a == 0 || b == 0)
  5. return a | b;
  6. while (((a | b) & 1) == 0)
  7. {
  8. deg++;
  9. a >>= 1;
  10. b >>= 1;
  11. }
  12. if (a)
  13. while ((a & 1) == 0)
  14. a >>= 1;
  15. while (b)
  16. {
  17. while ((b & 1) == 0)
  18. b >>= 1;
  19. if (a < b)
  20. b -= a;
  21. else
  22. {
  23. buf = a - b;
  24. a = b;
  25. b = buf;
  26. }
  27. b >>= 1;
  28. }
  29. return (a << deg);
  30. }

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

textual
Листинг программы
  1. #include <iostream>
  2.  
  3. template <int x, int y>
  4. struct gcd
  5. {
  6. private:
  7.   const static int _value1 = y,
  8.                    _value2 = x % y;
  9.   typedef gcd<static_cast<int>(_value1),
  10.               static_cast<int>(_value2)>
  11.               next_step_type;
  12.  
  13. public:
  14.   const static int value = next_step_type::value;
  15. };
  16.  
  17. template <int x>
  18. struct gcd<x, 0>
  19. {
  20.   const static int value = x;
  21. };
  22.  
  23. int main(){
  24.   std::cout << gcd<2344, 5432>::value << std::endl;
  25.   return 0;
  26. }

Объяснение кода листинга программы

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

  1. В первой строке объявляется шаблон структуры gcd, который принимает два целых числа x и y в качестве параметров.
  2. В блоке private структуры gcd объявляются две константы _value1 и _value2, которые инициализируются значениями y и x % y соответственно. % - это оператор взятия остатка от деления.
  3. Далее, используя оператор static_cast, мы приводим значения _value1 и _value2 к типу int для обеспечения корректной работы алгоритма.
  4. Затем мы определяем новый шаблон next_step_type, который будет использоваться в рекурсивном вызове функции gcd.
  5. В блоке public структуры gcd объявляется константа value, которая инициализируется значением next_step_type::value, т.е. результатом рекурсивного вызова функции gcd с новыми значениями _value1 и _value2.
  6. В конце кода в функции main выводится значение gcd<2344, 5432>::value на экран.
  7. В структуре gcd также присутствует специальный случай для вычисления НОД двух чисел, когда одно из них равно нулю. В этом случае возвращается второе число. Это сделано для корректной работы алгоритма. Список вызовов функций и значения переменных в данном коде:
  8. gcd<2344, 5432>::value - вызов функции gcd с аргументами 2344 и 5432, результат выводится на экран.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

13   голосов , оценка 3.923 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы