102 votes

Java : obtenir le plus grand diviseur commun

J'ai vu qu'une telle fonction existe pour BigInteger es decir BigInteger#gcd . Existe-t-il d'autres fonctions en Java qui fonctionnent également pour d'autres types ( int , long o Integer ) ? Il semble que cela ait un sens car java.lang.Math.gcd (avec toutes sortes de surcharges) mais il n'est pas là. Est-il ailleurs ?


(Ne confondez pas cette question avec "comment mettre cela en œuvre moi-même", s'il vous plaît).

7 votes

Pourquoi la réponse acceptée est-elle celle qui vous indique comment l'implémenter vous-même - tout en enveloppant une implémentation existante ? =)

0 votes

Je suis d'accord avec votre observation. Le PGCD devrait être une classe avec un tas de méthodes statiques surchargées qui prend deux nombres et donne le PGCD. Et elle devrait faire partie du paquet java.math.

149voto

Matt Points 3357

Pour autant que je sache, il n'existe pas de méthode intégrée pour les primitives. Mais quelque chose d'aussi simple que ceci devrait faire l'affaire :

public int gcd(int a, int b) {
   if (b==0) return a;
   return gcd(b,a%b);
}

Vous pouvez aussi le faire en une ligne si vous aimez ce genre de choses :

public int gcd(int a, int b) { return b==0 ? a : gcd(b, a%b); }

Il faut noter qu'il y a absolument pas de Il n'y a pas de différence entre les deux car ils se compilent dans le même code d'octet.

0 votes

Pour autant que je sache, cela fonctionne bien. Je viens de faire passer 100 000 nombres aléatoires par les deux méthodes et ils sont tous deux d'accord.

21 votes

C'est l'algorithme Euclidien... Il est très ancien et a fait ses preuves. fr.wikipedia.org/wiki/Euclidean_algorithm

0 votes

Oui, je peux le voir, mais j'ai besoin de plus de temps pour y réfléchir. Je l'aime bien.

94voto

Tony Ennis Points 4745

Pour int et long, en tant que primitives, pas vraiment. Pour Integer, il est possible que quelqu'un en ait écrit un.

Étant donné que BigInteger est un sur-ensemble (mathématique/fonctionnel) de int, Integer, long et Long, si vous devez utiliser ces types, convertissez-les en BigInteger, faites le GCD et reconvertissez le résultat.

private static int gcdThing(int a, int b) {
    BigInteger b1 = BigInteger.valueOf(a);
    BigInteger b2 = BigInteger.valueOf(b);
    BigInteger gcd = b1.gcd(b2);
    return gcd.intValue();
}

71 votes

BigInteger.valueOf(a).gcd(BigInteger.valueOf(b)).intValue() est bien meilleur.

2 votes

Quelques points de repère : stackoverflow.com/questions/21570890/

6 votes

Si cette fonction est appelée souvent (c'est-à-dire des millions de fois), vous ne devriez pas convertir int ou long en BigInteger. Une fonction n'utilisant que des valeurs primitives sera probablement plus rapide d'un ordre de grandeur. Vérifiez les autres réponses.

35voto

Xorlev Points 4658

Ou l'algorithme euclidien pour calculer le PGCD...

public int egcd(int a, int b) {
    if (a == 0)
        return b;

    while (b != 0) {
        if (a > b)
            a = a - b;
        else
            b = b - a;
    }

    return a;
}

3 votes

Juste pour clarifier : ce n'est absolument pas ce que je demandais.

14 votes

Dans ce cas, vous n'aviez pas précisé que vous ne vouliez pas d'implémentations alternatives puisqu'il n'en existait pas. Ce n'est que plus tard que vous avez modifié votre message pour ne pas rechercher d'implémentations. Je crois que d'autres ont répondu "non" de manière plus qu'adéquate.

4 votes

Cela serait lent si a est très grand et b petit. Les solutions en "%" seraient beaucoup plus rapides.

10voto

Tom Tucker Points 2542

C'est exactement ce que propose Jakarta Commons Math.

ArithmeticUtils.gcd(int p, int q)

-3voto

Mr-Al7lawe Points 1

Le % va nous donner le pgcd entre deux nombres, cela signifie:- % ou mod de grand_nombre/petit_nombre sont =gcd, et on l'écrit en java comme ceci big_number % small_number .

EX1 : pour deux entiers

  public static int gcd(int x1,int x2)
    {
        if(x1>x2)
        {
           if(x2!=0)
           {
               if(x1%x2==0)     
                   return x2;
                   return x1%x2;
                   }
           return x1;
           }
          else if(x1!=0)
          {
              if(x2%x1==0)
                  return x1;
                  return x2%x1;
                  }
        return x2;
        } 

EX2 : pour trois entiers

public static int gcd(int x1,int x2,int x3)
{

    int m,t;
    if(x1>x2)
        t=x1;
    t=x2;
    if(t>x3)
        m=t;
    m=x3;
    for(int i=m;i>=1;i--)
    {
        if(x1%i==0 && x2%i==0 && x3%i==0)
        {
            return i;
        }
    }
    return 1;
}

3 votes

C'est faux, par exemple gcd(42, 30) devrait être 6 mais c'est 12 par votre exemple. Mais 12 n'est pas un diviseur de 30 ni de 42. Vous devriez appeler gcd de manière récursive. Voir la réponse de Matt ou chercher l'algorithme euclidien sur Wikipedia.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X