Najmniejsza wspólna wielokrotność 3 lub więcej liczb


152

Jak obliczyć najmniejszą wspólną wielokrotność wielu liczb?

Jak dotąd byłem w stanie obliczyć to tylko między dwiema liczbami. Ale nie mam pojęcia, jak go rozszerzyć, aby obliczyć 3 lub więcej liczb.

Jak dotąd tak to zrobiłem

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

Z gcd jest funkcją obliczającą największy wspólny dzielnik dla liczb. Wykorzystanie algorytmu euklidesowego

Ale nie mogę wymyślić, jak to obliczyć dla 3 lub więcej liczb.


74
proszę nie oznaczaj tego jako zadania domowego. Próbuję znaleźć sposób na dopasowanie wielu kawałków blachy do płyty i muszę znaleźć sposób na dopasowanie metalu o różnej długości na tej samej płycie. Najlepszym sposobem na to jest LCM i GCD. Nie jestem programistą z matematyki. Dlatego spytałem.
paan

2
Dopasowywanie małych arkuszy do większego arkusza - pakowanie w pojemniki 2D?
Znak wysokiej wydajności

3
@HighPerformanceMark Tetris?
mbomb007

Odpowiedzi:


181

Możesz obliczyć LCM więcej niż dwóch liczb, obliczając iteracyjnie LCM dwóch liczb, tj

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

10
Ooooh podręcznik rekursji :)
Peter Wone

10
rekurencyjna definicja algorytmu nie musi oznaczać rekurencyjnej procedury. Możesz to po prostu zaimplementować w pętli. Dzięki za doskonałą odpowiedź.
Marius

144

W Pythonie (zmodyfikowany primes.py ):

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)

Stosowanie:

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

reduce()działa mniej więcej tak , że :

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

1
Nie jestem zaznajomiony z Pythonem, do czego służy funkcja Redukcja ()?
paan

17
Biorąc pod uwagę funkcję fi listę l = [a, b, c, d], redukuj (f, l) zwraca f (f (f (a, b), c), d). Jest to funkcjonalna implementacja „lcm można obliczyć iteracyjnie obliczając lcm bieżącej wartości i następnego elementu listy”.
A. Rex,

4
+1 za pokazanie rozwiązania, które może dostosować się do więcej niż trzech parametrów
OnesimusUnbound

czy możesz sprawić, by funkcja lcm zachowywała się jak funkcja lcmm, redukując się? Moją pierwszą myślą jest wykonanie funkcji lcm (), gdy są 2 argumenty, i zredukowanie (), gdy jest ich więcej.
endolit

1
@Hairy przecinek tworzy krotkę w Pythonie. W tym przypadku jest to równoważne z:t = a; a = b; b = t % b
jfs

26

Oto implementacja w stylu 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
To źle, że nie rozumiem, co masz na myśli przez „styl ECMA” = /
freitass

15

Poszedłbym z tym (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);
}

Tylko kilka wyjaśnień, ponieważ na pierwszy rzut oka nie wydaje się tak jasne, co robi ten kod:

Aggregate to metoda rozszerzenia Linq, więc nie możesz zapomnieć o dodaniu do odwołań przy użyciu System.Linq.

Aggregate otrzymuje funkcję kumulującą, dzięki czemu możemy wykorzystać właściwość lcm (a, b, c) = lcm (a, lcm (b, c)) nad IEnumerable. Więcej o agregacie

Obliczenia GCD wykorzystują algorytm Euklidesa .

Obliczenie lcm wykorzystuje Abs (a * b) / gcd (a, b), patrz Redukcja przez największy wspólny dzielnik .

Mam nadzieję że to pomoże,


6

Właśnie to rozgryzłem w 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

Poświęciłem nawet czas na napisanie własnej gcdfunkcji, ale znalazłem ją w Preludium! Dużo się dzisiaj nauczyłem: D


1
Możesz użyć foldr1 dla ostatniej linii: lcm ns = foldr1 lcm' nslublcm = foldr1 lcm'
Neil Mayhew

Możesz również zrezygnować z podpisów typu, aby uzyskać naprawdę minimalny wynik, jak Integralsugerujediv
Neil Mayhew

6

Kod w Pythonie, który nie wymaga funkcji dla 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)

Oto jak to wygląda w terminalu:

$ python lcm.py 10 15 17
510

6

Oto jednowierszowy Python (nie licząc importu), aby zwrócić LCM liczb całkowitych od 1 do 20 włącznie:

Importy Pythona 3.5+:

from functools import reduce
from math import gcd

Importy Pythona 2.7:

from fractions import gcd

Wspólna logika:

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

Zauważ, że zarówno w Pythonie 2, jak i Pythonie 3 reguły pierwszeństwa operatorów narzucają, że operatory *i //mają ten sam priorytet, więc są stosowane od lewej do prawej. Jako takie, x*y // zoznacza, (x*y) // za nie x * (y//z). Oba zwykle dają różne wyniki. Nie miałoby to większego znaczenia dla podziału typu float, ale ma znaczenie dla podziału podłogi .


3

Oto port C # implementacji Virgila 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

Funkcja znajdowania lcm dowolnej listy liczb:

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

2

Używając LINQ możesz napisać:

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

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

Powinien dodać using System.Linq;i nie zapomnieć o obsłudze wyjątków ...


2

I wersja 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

Tutaj jest w 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

możesz to zrobić w inny sposób - Niech będzie n liczb. Weź parę kolejnych liczb i zapisz jej lcm w innej tablicy. Robiąc to w pierwszej iteracji, program wykonuje n / 2 iteracji, a następnie wybiera parę zaczynającą się od 0, jak (0,1), (2,3) itd. Oblicz ich LCM i zapisz w innej tablicy. Rób to, dopóki nie zostanie ci jedna tablica. (nie można znaleźć lcm, jeśli n jest nieparzyste)


1

W R możemy użyć funkcji mGCD (x) i mLCM (x) z numerów pakietów , aby obliczyć największy wspólny dzielnik i najmniejszą wspólną wielokrotność dla wszystkich liczb w wektorze całkowitoliczbowym x razem:

    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

Styl 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
Zadzwoniłeś, gcd(a, b)ale gdcfunkcja oczekuje tablicy, więc zamierzałeś ją wywołaćgcd([a, b])
João Pinto Jerónimo

to zdecydowanie najbardziej elegancka odpowiedź
Lokua

1

Dla zabawy, implementacja powłoki (prawie każdej powłoki):

#!/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"

spróbuj z:

$ ./script 2 3 4 5 6

dostać

60

Największe dane wejściowe i wynik powinny być mniejsze niż (2^63)-1lub matematyka powłoki się zawinie.


1

Szukałem gcd i lcm elementów tablicy i znalazłem dobre rozwiązanie w poniższym linku.

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

który zawiera następujący kod. Algorytm dla gcd wykorzystuje algorytm euklidesowy wyjaśniony dobrze w linku poniżej.

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

Oto implementacja 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

Kredyty trafiają do @ T3db0t z jego odpowiedzią powyżej (kod w stylu ECMA) .


0

GCD wymaga niewielkiej korekty liczb ujemnych:

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

Co powiesz na to?

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

Mamy działającą implementację Least Common Multiple w Calculla która działa dla dowolnej liczby wejść wyświetlających również kroki.

Co robimy to:

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.

I to wszystko - masz swój lcm.


0

LCM jest zarówno asocjacyjna, jak i przemienna.

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

oto przykładowy kod w 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

Metoda compLCM pobiera wektor i zwraca LCM. Wszystkie liczby znajdują się w obrębie wektora 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 

Kod jest ceniony, ale jeśli możesz dodać komentarze opisujące, jak to działa, jest to doceniane jeszcze bardziej.
Alex Riley

Chociaż ten fragment kodu może rozwiązać problem, w tym wyjaśnienie naprawdę pomaga poprawić jakość Twojego posta. Pamiętaj, że odpowiadasz na pytanie do czytelników w przyszłości, a nie tylko osoba, która zapyta teraz! Proszę edytować swoje odpowiedzi, aby dodać wyjaśnienie, i dać wskazówkę co zastosować ograniczenia i założenia.
Toby Speight

0

Dla każdego, kto szuka szybko działającego kodu, spróbuj tego:

Napisałem funkcję, lcm_n(args, num) która oblicza i zwraca lcm wszystkich liczb w tablicy args. Drugi parametr numto liczba liczb w tablicy.

Umieść wszystkie te liczby w tablicy, argsa następnie wywołaj funkcję taką jaklcm_n(args,num);

Ta funkcja zwraca lcm wszystkich tych liczb.

Oto implementacja funkcji 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);
    }
}

Ta funkcja wymaga poniższych dwóch funkcji do działania. Więc po prostu dodaj je razem z nim.

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

W Pythonie:

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

To jest to, czego użyłem -

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

dla pythona 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

W Rubim jest to tak proste, jak:

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

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

(testowane na Ruby 2.2.10 i 2.6.3.)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.