Multiple le moins commun pour 3 nombres ou plus


152

Comment calculez-vous le plus petit commun multiple de plusieurs nombres?

Jusqu'à présent, je n'ai pu le calculer qu'entre deux nombres. Mais je n'ai aucune idée de comment l'étendre pour calculer 3 nombres ou plus.

Jusqu'ici c'est comme ça que je l'ai fait

LCM = num1 * num2 /  gcd ( num1 , num2 )

Avec pgcd est la fonction pour calculer le plus grand diviseur commun des nombres. Utilisation de l'algorithme euclidien

Mais je ne peux pas comprendre comment le calculer pour 3 nombres ou plus.


74
veuillez ne pas marquer cela comme des devoirs. J'essaie de trouver un moyen d'ajuster plusieurs morceaux de feuilles de métal sur une plaque et j'ai besoin de trouver un moyen d'adapter un métal de différentes longueurs sur la même plaque. LCM et GCD sont le meilleur moyen d'y parvenir. Je suis programmeur, pas mathématicien. C'est pourquoi j'ai demandé.
paan le

2
Insertion de petites feuilles dans une feuille plus grande - emballage en bac 2D?
High Performance Mark

3
@HighPerformanceMark Tetris?
mbomb007

Réponses:


181

Vous pouvez calculer le LCM de plus de deux nombres en calculant itérativement le LCM de deux nombres, c'est-à-dire

lcm(a,b,c) = lcm(a,lcm(b,c))

10
Ooooh textbook recursion :)
Peter Wone

10
une définition d'algorithme récursif ne signifie pas nécessairement un sous-programme récursif. Vous pouvez l'implémenter dans une boucle assez simplement. Merci pour la réponse parfaite.
Marius

144

En Python ( nombres premiers.py modifiés ):

def gcd(a, b):
    """Return greatest common divisor using Euclid's Algorithm."""
    while b:      
        a, b = b, a % b
    return a

def lcm(a, b):
    """Return lowest common multiple."""
    return a * b // gcd(a, b)

def lcmm(*args):
    """Return lcm of args."""   
    return reduce(lcm, args)

Usage:

>>> lcmm(100, 23, 98)
112700
>>> lcmm(*range(1, 20))
232792560

reduce()fonctionne quelque chose comme ça :

>>> f = lambda a,b: "f(%s,%s)" % (a,b)
>>> print reduce(f, "abcd")
f(f(f(a,b),c),d)

1
Je ne suis pas familier avec python, que fait reduction ()?
paan le

17
Étant donné une fonction f et une liste l = [a, b, c, d], réduire (f, l) renvoie f (f (f (a, b), c), d). C'est l'implémentation fonctionnelle de "lcm peut être calculé en calculant de manière itérative le lcm de la valeur actuelle et l'élément suivant de la liste".
A. Rex le

4
+1 pour montrer une solution qui peut s'adapter à plus de trois paramètres
OnesimusUnbound

pouvez-vous faire en sorte que la fonction lcm se comporte comme la fonction lcmm en se réduisant? Ma première pensée est de lui faire faire le lcm () quand il y a 2 arguments, et faire le reduction () quand il y en a plus.
endolith

1
@Hairy comma crée un tuple en Python. Dans ce cas, cela équivaut à:t = a; a = b; b = t % b
jfs

26

Voici une implémentation de style ECMA:

function gcd(a, b){
    // Euclidean algorithm
    var t;
    while (b != 0){
        t = b;
        b = a % b;
        a = t;
    }
    return a;
}

function lcm(a, b){
    return (a * b / gcd(a, b));
}

function lcmm(args){
    // Recursively iterate through pairs of arguments
    // i.e. lcm(args[0], lcm(args[1], lcm(args[2], args[3])))

    if(args.length == 2){
        return lcm(args[0], args[1]);
    } else {
        var arg0 = args[0];
        args.shift();
        return lcm(arg0, lcmm(args));
    }
}

2
Cela me fait du mal de ne pas comprendre ce que vous entendez par "style ECMA" = /
freitass

15

J'irais avec celui-ci (C #):

static long LCM(long[] numbers)
{
    return numbers.Aggregate(lcm);
}
static long lcm(long a, long b)
{
    return Math.Abs(a * b) / GCD(a, b);
}
static long GCD(long a, long b)
{
    return b == 0 ? a : GCD(b, a % b);
}

Juste quelques clarifications, car à première vue, ce que fait ce code ne semble pas si clair:

Aggregate est une méthode d'extension Linq, vous ne pouvez donc pas oublier d'ajouter en utilisant System.Linq à vos références.

Aggregate obtient une fonction d'accumulation afin que nous puissions utiliser la propriété lcm (a, b, c) = lcm (a, lcm (b, c)) sur un IEnumerable. En savoir plus sur les agrégats

Le calcul GCD utilise l' algorithme euclidien .

Le calcul de lcm utilise Abs (a * b) / pgcd (a, b), référez-vous à Réduction par le plus grand diviseur commun .

J'espère que cela t'aides,


6

Je viens de comprendre cela dans Haskell:

lcm' :: Integral a => a -> a -> a
lcm' a b = a`div`(gcd a b) * b
lcm :: Integral a => [a] -> a
lcm (n:ns) = foldr lcm' n ns

J'ai même pris le temps d'écrire ma propre gcdfonction, pour la retrouver dans Prelude! Beaucoup d'apprentissage pour moi aujourd'hui: D


1
Vous pouvez utiliser foldr1 pour la dernière ligne: lcm ns = foldr1 lcm' nsoulcm = foldr1 lcm'
Neil Mayhew

Vous pouvez également vous passer des signatures de type, pour un résultat vraiment minimal, comme l' Integralimpliquediv
Neil Mayhew

6

Un code Python qui ne nécessite pas de fonction pour gcd:

from sys import argv 

def lcm(x,y):
    tmp=x
    while (tmp%y)!=0:
        tmp+=x
    return tmp

def lcmm(*args):
    return reduce(lcm,args)

args=map(int,argv[1:])
print lcmm(*args)

Voici à quoi cela ressemble dans le terminal:

$ python lcm.py 10 15 17
510

6

Voici un Python one-liner (sans compter les importations) pour renvoyer le LCM des entiers de 1 à 20 inclus:

Importations Python 3.5+:

from functools import reduce
from math import gcd

Importe Python 2.7:

from fractions import gcd

Logique commune:

lcm = reduce(lambda x,y: x*y // gcd(x, y), range(1, 21))

Notez que dans Python 2 et Python 3 , les règles de priorité des opérateurs imposent que les opérateurs *et //aient la même priorité, et s'appliquent donc de gauche à droite. En tant que tel, x*y // zsignifie (x*y) // zet non x * (y//z). Les deux produisent généralement des résultats différents. Cela n'aurait pas eu autant d'importance pour la division des flotteurs que pour la division au sol .


3

Voici un port C # de l'implémentation de Virgil Disgr4ce:

public class MathUtils
{
    /// <summary>
    /// Calculates the least common multiple of 2+ numbers.
    /// </summary>
    /// <remarks>
    /// Uses recursion based on lcm(a,b,c) = lcm(a,lcm(b,c)).
    /// Ported from http://stackoverflow.com/a/2641293/420175.
    /// </remarks>
    public static Int64 LCM(IList<Int64> numbers)
    {
        if (numbers.Count < 2)
            throw new ArgumentException("you must pass two or more numbers");
        return LCM(numbers, 0);
    }

    public static Int64 LCM(params Int64[] numbers)
    {
        return LCM((IList<Int64>)numbers);
    }

    private static Int64 LCM(IList<Int64> numbers, int i)
    {
        // Recursively iterate through pairs of arguments
        // i.e. lcm(args[0], lcm(args[1], lcm(args[2], args[3])))

        if (i + 2 == numbers.Count)
        {
            return LCM(numbers[i], numbers[i+1]);
        }
        else
        {
            return LCM(numbers[i], LCM(numbers, i+1));
        }
    }

    public static Int64 LCM(Int64 a, Int64 b)
    {
        return (a * b / GCD(a, b));
    }

    /// <summary>
    /// Finds the greatest common denominator for 2 numbers.
    /// </summary>
    /// <remarks>
    /// Also from http://stackoverflow.com/a/2641293/420175.
    /// </remarks>
    public static Int64 GCD(Int64 a, Int64 b)
    {
        // Euclidean algorithm
        Int64 t;
        while (b != 0)
        {
            t = b;
            b = a % b;
            a = t;
        }
        return a;
    }
}'

3

Fonction pour trouver lcm de n'importe quelle liste de nombres:

 def function(l):
     s = 1
     for i in l:
        s = lcm(i, s)
     return s

2

En utilisant LINQ, vous pouvez écrire:

static int LCM(int[] numbers)
{
    return numbers.Aggregate(LCM);
}

static int LCM(int a, int b)
{
    return a * b / GCD(a, b);
}

Doit ajouter using System.Linq;et n'oubliez pas de gérer les exceptions ...


2

Et la version Scala:

def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b)
def gcd(nums: Iterable[Int]): Int = nums.reduce(gcd)
def lcm(a: Int, b: Int): Int = if (a == 0 || b == 0) 0 else a * b / gcd(a, b)
def lcm(nums: Iterable[Int]): Int = nums.reduce(lcm)

2

Le voici à Swift .

// Euclid's algorithm for finding the greatest common divisor
func gcd(_ a: Int, _ b: Int) -> Int {
  let r = a % b
  if r != 0 {
    return gcd(b, r)
  } else {
    return b
  }
}

// Returns the least common multiple of two numbers.
func lcm(_ m: Int, _ n: Int) -> Int {
  return m / gcd(m, n) * n
}

// Returns the least common multiple of multiple numbers.
func lcmm(_ numbers: [Int]) -> Int {
  return numbers.reduce(1) { lcm($0, $1) }
}

1

vous pouvez le faire d'une autre manière - Soit n nombres. Prenez une paire de nombres consécutifs et enregistrez son lcm dans un autre tableau. Faire cela au premier programme d'itération fait n / 2 itérations.Ensuite, la prochaine paire de ramassage à partir de 0 comme (0,1), (2,3) et ainsi de suite.Calculez leur LCM et stockez-les dans un autre tableau. Faites-le jusqu'à ce qu'il ne vous reste plus qu'une seule matrice. (il n'est pas possible de trouver lcm si n est impair)


1

Dans R, nous pouvons utiliser les fonctions mGCD (x) et mLCM (x) à partir des numéros de package , pour calculer ensemble le plus grand diviseur commun et le plus petit commun multiple pour tous les nombres du vecteur entier x:

    library(numbers)
    mGCD(c(4, 8, 12, 16, 20))
[1] 4
    mLCM(c(8,9,21))
[1] 504
    # Sequences
    mLCM(1:20)
[1] 232792560

1

Style ES6

function gcd(...numbers) {
  return numbers.reduce((a, b) => b === 0 ? a : gcd(b, a % b));
}

function lcm(...numbers) {
  return numbers.reduce((a, b) => Math.abs(a * b) / gcd(a, b));
}

1
Vous avez appelé gcd(a, b)mais la gdcfonction attend un tableau donc vous vouliez appelergcd([a, b])
João Pinto Jerónimo

c'est de loin la réponse la plus élégante
Lokua

1

Juste pour le plaisir, une implémentation shell (presque n'importe quel shell):

#!/bin/sh
gcd() {   # Calculate $1 % $2 until $2 becomes zero.
      until [ "$2" -eq 0 ]; do set -- "$2" "$(($1%$2))"; done
      echo "$1"
      }

lcm() {   echo "$(( $1 / $(gcd "$1" "$2") * $2 ))";   }

while [ $# -gt 1 ]; do
    t="$(lcm "$1" "$2")"
    shift 2
    set -- "$t" "$@"
done
echo "$1"

essayez-le avec:

$ ./script 2 3 4 5 6

obtenir

60

L'entrée et le résultat les plus importants doivent être inférieurs à (2^63)-1ou les mathématiques du shell s'enrouleront.


1

Je cherchais gcd et lcm d'éléments de tableau et j'ai trouvé une bonne solution dans le lien suivant.

https://www.hackerrank.com/challenges/between-two-sets/forum

qui comprend le code suivant. L'algorithme pour pgcd utilise l'algorithme euclidien bien expliqué dans le lien ci-dessous.

https://www.khanacademy.org/computing/computer-science/cryptography/modarithmetic/a/the-euclidean-algorithm

private static int gcd(int a, int b) {
    while (b > 0) {
        int temp = b;
        b = a % b; // % is remainder
        a = temp;
    }
    return a;
}

private static int gcd(int[] input) {
    int result = input[0];
    for (int i = 1; i < input.length; i++) {
        result = gcd(result, input[i]);
    }
    return result;
}

private static int lcm(int a, int b) {
    return a * (b / gcd(a, b));
}

private static int lcm(int[] input) {
    int result = input[0];
    for (int i = 1; i < input.length; i++) {
        result = lcm(result, input[i]);
    }
    return result;
}

1

Voici l' implémentation PHP :

    // https://stackoverflow.com/q/12412782/1066234
    function math_gcd($a,$b) 
    {
        $a = abs($a); 
        $b = abs($b);
        if($a < $b) 
        {
            list($b,$a) = array($a,$b); 
        }
        if($b == 0) 
        {
            return $a;      
        }
        $r = $a % $b;
        while($r > 0) 
        {
            $a = $b;
            $b = $r;
            $r = $a % $b;
        }
        return $b;
    }

    function math_lcm($a, $b)
    {
        return ($a * $b / math_gcd($a, $b));
    }

    // https://stackoverflow.com/a/2641293/1066234
    function math_lcmm($args)
    {
        // Recursively iterate through pairs of arguments
        // i.e. lcm(args[0], lcm(args[1], lcm(args[2], args[3])))

        if(count($args) == 2)
        {
            return math_lcm($args[0], $args[1]);
        }
        else 
        {
            $arg0 = $args[0];
            array_shift($args);
            return math_lcm($arg0, math_lcmm($args));
        }
    }

    // fraction bonus
    function math_fraction_simplify($num, $den) 
    {
        $g = math_gcd($num, $den);
        return array($num/$g, $den/$g);
    }


    var_dump( math_lcmm( array(4, 7) ) ); // 28
    var_dump( math_lcmm( array(5, 25) ) ); // 25
    var_dump( math_lcmm( array(3, 4, 12, 36) ) ); // 36
    var_dump( math_lcmm( array(3, 4, 7, 12, 36) ) ); // 252

Les crédits vont à @ T3db0t avec sa réponse ci-dessus (code de style ECMA) .


0

GCD a besoin d'une petite correction pour les nombres négatifs:

def gcd(x,y):
  while y:
    if y<0:
      x,y=-x,-y
    x,y=y,x % y
    return x

def gcdl(*list):
  return reduce(gcd, *list)

def lcm(x,y):
  return x*y / gcd(x,y)

def lcml(*list):
  return reduce(lcm, *list)

0

Que dis-tu de ça?

from operator import mul as MULTIPLY

def factors(n):
    f = {} # a dict is necessary to create 'factor : exponent' pairs 
    divisor = 2
    while n > 1:
        while (divisor <= n):
            if n % divisor == 0:
                n /= divisor
                f[divisor] = f.get(divisor, 0) + 1
            else:
                divisor += 1
    return f


def mcm(numbers):
    #numbers is a list of numbers so not restricted to two items
    high_factors = {}
    for n in numbers:
        fn = factors(n)
        for (key, value) in fn.iteritems():
            if high_factors.get(key, 0) < value: # if fact not in dict or < val
                high_factors[key] = value
    return reduce (MULTIPLY, ((k ** v) for k, v in high_factors.items()))

0

Nous avons une implémentation fonctionnelle de Least Common Multiple sur Calculla qui fonctionne pour n'importe quel nombre d'entrées affichant également les étapes.

Ce que nous faisons est:

0: Assume we got inputs[] array, filled with integers. So, for example:
   inputsArray = [6, 15, 25, ...]
   lcm = 1

1: Find minimal prime factor for each input.
   Minimal means for 6 it's 2, for 25 it's 5, for 34 it's 17
   minFactorsArray = []

2: Find lowest from minFactors:
   minFactor = MIN(minFactorsArray)

3: lcm *= minFactor

4: Iterate minFactorsArray and if the factor for given input equals minFactor, then divide the input by it:
  for (inIdx in minFactorsArray)
    if minFactorsArray[inIdx] == minFactor
      inputsArray[inIdx] \= minFactor

5: repeat steps 1-4 until there is nothing to factorize anymore. 
   So, until inputsArray contains only 1-s.

Et c'est tout - vous avez votre lcm.


0

LCM est à la fois associatif et commutatif.

LCM (a, b, c) = LCM (LCM (a, b), c) = LCM (a, LCM (b, c))

voici un exemple de code en C:

int main()
{
  int a[20],i,n,result=1;  // assumption: count can't exceed 20
  printf("Enter number of numbers to calculate LCM(less than 20):");
  scanf("%d",&n);
  printf("Enter %d  numbers to calculate their LCM :",n);
  for(i=0;i<n;i++)
    scanf("%d",&a[i]);
 for(i=0;i<n;i++)
   result=lcm(result,a[i]);
 printf("LCM of given numbers = %d\n",result);
 return 0;
}

int lcm(int a,int b)
{
  int gcd=gcd_two_numbers(a,b);
  return (a*b)/gcd;
}

int gcd_two_numbers(int a,int b)
{
   int temp;
   if(a>b)
   {
     temp=a;
     a=b;
     b=temp;
   }
  if(b%a==0)
    return a;
  else
    return gcd_two_numbers(b%a,a);
}

0

La méthode compLCM prend un vecteur et renvoie LCM. Tous les nombres sont dans le vecteur in_numbers.

int mathOps::compLCM(std::vector<int> &in_numbers)
 {
    int tmpNumbers = in_numbers.size();
    int tmpMax = *max_element(in_numbers.begin(), in_numbers.end());
    bool tmpNotDividable = false;

    while (true)
    {
        for (int i = 0; i < tmpNumbers && tmpNotDividable == false; i++)
        {
            if (tmpMax % in_numbers[i] != 0 )
                tmpNotDividable = true;
        }

        if (tmpNotDividable == false)
            return tmpMax;
        else
            tmpMax++;
    }
}

0
clc;

data = [1 2 3 4 5]

LCM=1;

for i=1:1:length(data)

    LCM = lcm(LCM,data(i))

end 

Le code est apprécié, mais si vous pouvez ajouter des commentaires détaillant son fonctionnement, il l'appréciera encore plus.
Alex Riley

Bien que cet extrait de code puisse résoudre la question, inclure une explication aide vraiment à améliorer la qualité de votre message. N'oubliez pas que vous répondez à la question des lecteurs à l'avenir, pas seulement à la personne qui la pose maintenant! Veuillez modifier votre réponse pour ajouter une explication et donner une indication des limites et des hypothèses applicables.
Toby Speight

0

Pour tous ceux qui recherchent un code de travail rapide, essayez ceci:

J'ai écrit une fonction lcm_n(args, num) qui calcule et renvoie le lcm de tous les nombres du tableau args. Le deuxième paramètre numest le nombre de nombres dans le tableau.

Mettez tous ces nombres dans un tableau args, puis appelez la fonction commelcm_n(args,num);

Cette fonction renvoie le lcm de tous ces nombres.

Voici l'implémentation de la fonction lcm_n(args, num):

int lcm_n(int args[], int num) //lcm of more than 2 numbers
{
    int i, temp[num-1];

    if(num==2)
    {
        return lcm(args[0], args[1]);
    }
    else
    {
        for(i=0;i<num-1;i++)
        {
           temp[i] = args[i];   
        }

        temp[num-2] = lcm(args[num-2], args[num-1]);
        return lcm_n(temp,num-1);
    }
}

Cette fonction a besoin de moins de deux fonctions pour fonctionner. Alors, ajoutez-les simplement avec lui.

int lcm(int a, int b) //lcm of 2 numbers
{
    return (a*b)/gcd(a,b);
}


int gcd(int a, int b) //gcd of 2 numbers
{
    int numerator, denominator, remainder;

    //Euclid's algorithm for computing GCD of two numbers
    if(a > b)
    {
        numerator = a;
        denominator = b;
    }
    else
    {
        numerator = b;
        denominator = a;
    }
    remainder = numerator % denominator;

    while(remainder != 0)
    {
        numerator   = denominator;
        denominator = remainder;
        remainder   = numerator % denominator;
    }

    return denominator;
}

0

int gcd(int a, int b) { if (b == 0) return a; return gcd(b, a%b); } int lcm(int[] a, int n) { int res = 1, i; for (i = 0; i < n; i++) { res = res*a[i]/gcd(res, a[i]); } return res; }


0

En python:

def lcm(*args):
    """Calculates lcm of args"""
    biggest = max(args) #find the largest of numbers
    rest = [n for n in args if n != biggest] #the list of the numbers without the largest
    factor = 1 #to multiply with the biggest as long as the result is not divisble by all of the numbers in the rest
    while True:
        #check if biggest is divisble by all in the rest:
        ans = False in [(biggest * factor) % n == 0 for n in rest]
        #if so the clm is found break the loop and return it, otherwise increment factor by 1 and try again
        if not ans:
            break
        factor += 1
    biggest *= factor
    return "lcm of {0} is {1}".format(args, biggest)

>>> lcm(100,23,98)
'lcm of (100, 23, 98) is 112700'
>>> lcm(*range(1, 20))
'lcm of (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19) is 232792560'

0

C'est ce que j'ai utilisé -

def greater(n):

      a=num[0]

      for i in range(0,len(n),1):
       if(a<n[i]):
        a=n[i]
      return a

r=input('enter limit')

num=[]

for x in range (0,r,1):

    a=input('enter number ')
    num.append(a)
a= greater(num)

i=0

while True:

    while (a%num[i]==0):
        i=i+1
        if(i==len(num)):
               break
    if i==len(num):
        print 'L.C.M = ',a
        break
    else:
        a=a+1
        i=0

0

pour python 3:

from functools import reduce

gcd = lambda a,b: a if b==0 else gcd(b, a%b)
def lcm(lst):        
    return reduce(lambda x,y: x*y//gcd(x, y), lst)  

0

Dans Ruby, c'est aussi simple que:

> [2, 3, 4, 6].reduce(:lcm)
=> 12

> [16, 32, 96].reduce(:gcd)
=> 16

(testé sur Ruby 2.2.10 et 2.6.3.)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.