web-dev-qa-db-fra.com

Fonction GCD dans la bibliothèque c ++ sans cmath

J'écris une classe de chiffres mixtes et j'ai besoin d'une fonction de "plus grand diviseur commun" rapide et facile. Quelqu'un peut-il me donner le code ou un lien vers le code?

24
Connor Black

Je suis tenté de voter pour fermer - il semble difficile de croire qu'une mise en œuvre serait difficile à trouver, mais qui sait avec certitude.

template <typename Number>
Number GCD(Number u, Number v) {
    while (v != 0) {
        Number r = u % v;
        u = v;
        v = r;
    }
    return u;
}

En C++ 17 ou plus récent, vous pouvez simplement #include <numeric>, et utilise std::gcd (et si vous vous souciez du gcd, il est fort probable que vous serez intéressé par le std::lcm qui a également été ajouté).

38
Jerry Coffin

La bibliothèque d'algorithmes libstdc ++ a une fonction gcd cachée (j'utilise g ++ 4.6.3).

#include <iostream>
#include <algorithm>

int main()
{
  cout << std::__gcd(100,24);
  return 0;
}

Je vous en prie :)

MISE À JOUR: Comme l'a noté @ chema989, en C++ 17, il y a la fonction std::gcd() disponible avec l'en-tête <numeric>.

51
Tomasz Posłuszny

Une version récursive rapide:

unsigned int gcd (unsigned int n1, unsigned int n2) {
    return (n2 == 0) ? n1 : gcd (n2, n1 % n2);
}

ou la version itérative équivalente si vous êtes violemment opposé à la récursivité (une):

unsigned int gcd (unsigned int n1, unsigned int n2) {
    unsigned int tmp;
    while (n2 != 0) {
        tmp = n1;
        n1 = n2;
        n2 = tmp % n2;
    }
    return n1;
}

Il suffit de substituer dans votre propre type de données, la comparaison zéro, la méthode d'affectation et de module (si vous utilisez un type non basique comme une classe bignum, par exemple).

Cette fonction provenait en fait d'un réponse précédente pour travailler sur les rapports d'aspect intégraux pour les tailles d'écran, mais la source d'origine était l'algorithme euclidien que j'ai appris il y a longtemps, détaillé ici sur Wikipedia si vous voulez connaître les mathématiques derrière cela.


(une) Le problème avec certaines solutions récursives est qu'elles approchent la réponse si lentement que vous avez tendance à manquer d'espace de pile avant d'y arriver, comme avec le très mal pensé (pseudo-code):

def sum (a:unsigned, b:unsigned):
    if b == 0: return a
    return sum (a + 1, b - 1)

Vous trouverez cela très coûteux sur quelque chose comme sum (1, 1000000000) lorsque vous (essayez) d'utiliser jusqu'à un milliard de trames de pile. Le cas d'utilisation idéal pour la récursivité est quelque chose comme une recherche binaire où vous réduisez de moitié l'espace de solution pour chaque itération. Le plus grand diviseur commun est également celui où l'espace de solution se réduit rapidement, de sorte que les craintes d'une utilisation massive de la pile n'y sont pas fondées.

19
paxdiablo

Pour C++ 17, vous pouvez utiliser std::gcd défini dans l'en-tête <numeric>:

auto res = std::gcd(10, 20);
8
chema989

L'algorithme Euclidean est assez facile à écrire en C.

int gcd(int a, int b) {
  while (b != 0)  {
    int t = b;
    b = a % b;
    a = t;
  }
  return a;
}
5
David Nehme