Найменше загальне кратне для 3 або більше чисел


152

Як обчислити найменше загальне кратне число чисел?

Поки що я міг обчислити це лише між двома числами. Але поняття не маю, як розширити його, щоб обчислити 3 і більше чисел.

Поки що це я зробив

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

З gcd є функція обчислення найбільшого спільного дільника чисел. Використання евклідового алгоритму

Але я не можу зрозуміти, як обчислити це для 3 чи більше чисел.


74
будь ласка, не позначайте це домашнім завданням. Я намагаюся знайти спосіб прилаштувати декілька шматків металевих листів до плити, і мені потрібно знайти спосіб розміщення металу різної довжини на одній пластині. LCM та GCD - найкращий спосіб зробити це. Я програміст, а не математик. Ось чому я запитав.
паан

2
Поміщення маленьких аркушів у більший аркуш - 2D упаковка для сміття?
Марка високої продуктивності

3
@HighPerformanceMark Tetris?
mbomb007

Відповіді:


181

Можна обчислити LCM з більш ніж двох чисел шляхом ітеративного обчислення LCM двох чисел, тобто

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

10
Рекурсія підручника Ooooh :)
Пітер Вун

10
визначення рекурсивного алгоритму не обов'язково означає рекурсивну підпрограму. Ви можете реалізувати це в циклі досить просто. Дякую за ідеальну відповідь.
Маріус

144

У Python (модифікований 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)

Використання:

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

reduce()працює що - щось на зразок , що :

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

1
Я не знайомий з python, що робить зниження ()?
паан

17
Давши функцію f та список l = [a, b, c, d], зменшення (f, l) повертає f (f (f (a, b), c), d). Це функціональна реалізація "lcm можна обчислити за допомогою ітеративного обчислення lcm поточного значення та наступного елемента списку."
А. Рекс

4
+1 для показу рішення, яке може адаптуватися до більш ніж трьох параметрів
OnesimusUnbound

чи можете ви змусити функцію lcm поводитись як функція lcmm, зменшуючи себе? Перша моя думка - змусити це робити lcm (), коли є два аргументи, і зменшити (), коли їх більше.
ендоліт

1
@Hairy Кома створює кортеж у Python. У цьому випадку це рівнозначно:t = a; a = b; b = t % b
jfs

26

Ось реалізація в стилі 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
Дуже погано, що я не розумію, що ви маєте на увазі під "ECMA-style" = /
freitass

15

Я б пішов з цим (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);
}

Лише деякі роз’яснення, оскільки на перший погляд це не так зрозуміло, що робить цей код:

Агрегат - це метод розширення Linq, тому ви не можете забути додати, використовуючи System.Linq до своїх посилань.

Сукупність отримує накопичувальну функцію, тому ми можемо скористатися властивістю lcm (a, b, c) = lcm (a, lcm (b, c)) над IEnumerable. Детальніше про Aggregate

Для обчислення GCD використовується алгоритм Евкліда .

Для обчислення lcm використовується Abs (a * b) / gcd (a, b), див. Зменшення найбільшим загальним дільником .

Сподіваюся, це допомагає,


6

Я щойно зрозумів це в 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

Я навіть взяв час, щоб написати власну gcdфункцію, лише знайти її в Прелюдії! Сьогодні для мене багато навчання: D


1
Ви можете використовувати foldr1 для останнього рядка: lcm ns = foldr1 lcm' nsабоlcm = foldr1 lcm'
Ніл Мейхью,

Ви також можете відмовитися від підписів типу для дійсно мінімального результату, як Integralмається на увазіdiv
Ніл Мейхью,

6

Деякий код Python, який не потребує функції для 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)

Ось як це виглядає в терміналі:

$ python lcm.py 10 15 17
510

6

Ось однолінійний Python (без урахування імпорту) для повернення LCM цілих чисел від 1 до 20 включно:

Python 3.5+ імпортує:

from functools import reduce
from math import gcd

Python 2.7 імпортує:

from fractions import gcd

Загальна логіка:

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

Зауважте, що і в Python 2, і в Python 3 правила пріоритетності операторів диктують, що *і //оператори мають однаковий пріоритет, і тому вони застосовуються зліва направо. Як такий, x*y // zозначає (x*y) // zі ні x * (y//z). Вони, як правило, дають різні результати. Це не мало би значення для поплавкового поділу, але це для підлогового поділу .


3

Ось порт C # на реалізацію 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;
    }
}'


2

За допомогою LINQ ви можете написати:

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

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

Слід додати using System.Linq;та не забувати обробляти винятки ...


2

І версія 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

Ось він у Свіфті .

// 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

Ви можете зробити це іншим способом - Нехай буде n чисел. Зробіть пару послідовних чисел і збережіть його lcm в іншому масиві. Здійснюючи це на першій програмі ітерації, робиться n / 2 ітерації. Потім виберіть пару, починаючи з 0 (0,1), (2,3) тощо. Обчисліть їх LCM і зберігайте в іншому масиві. Робіть це, поки вам не залишиться один масив. (неможливо знайти lcm, якщо n непарне)


1

У R ми можемо використовувати функції mGCD (x) та mLCM (x) з номерів пакунків , щоб обчислити найбільший спільний дільник і найменше спільний кратний для всіх чисел у цілому векторі 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

Стиль 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
Ви зателефонували, gcd(a, b)але gdcфункція очікує масиву, тому ви мали намір зателефонуватиgcd([a, b])
João Pinto Jerónimo

це найелегантніша відповідь на сьогодні
Локуа

1

Для розваги реалізація оболонки (майже будь-якої оболонки):

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

спробуйте:

$ ./script 2 3 4 5 6

отримати

60

Найбільший вхід і результат повинні бути меншими, (2^63)-1або математика оболонки завернеться.


1

Я шукав gcd та lcm елементів масиву і знайшов хороше рішення за наступним посиланням.

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

який включає наступний код. Алгоритм використання gcd використовує алгоритм Евкліда, пояснений добре за посиланням нижче.

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

Ось реалізація 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

Кредити переходять до @ T3db0t з його відповіддю вище (код у стилі ECMA) .


0

GCD потребує невеликої корекції для від'ємних чисел:

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

Як щодо цього?

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

Ми працюємо над впровадженням найменшого загального множини для обчислення, яке працює для будь-якої кількості входів, що також показують кроки.

Що ми робимо:

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.

І це все - у вас є ваш lcm.


0

LCM є і асоціативним, і комутативним.

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

ось зразок коду на 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

Метод compLCM приймає вектор і повертає LCM. Усі числа знаходяться у векторних номерах.

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 

Кодекс цінується, але якщо ви можете додати коментарі, в яких детально описується, як це працює, його цінують ще більше.
Алекс Райлі

Хоча цей фрагмент коду може вирішити питання, зокрема пояснення дійсно допомагає покращити якість вашої публікації. Пам’ятайте, що ви відповідаєте на запитання читачів у майбутньому, а не лише про людину, яка зараз запитує! Будь ласка, відредагуйте свою відповідь, щоб додати пояснення та вказати, які обмеження та припущення застосовуються.
Toby Speight

0

Для всіх, хто шукає швидкий робочий код, спробуйте це:

Я написав функцію, lcm_n(args, num) яка обчислює та повертає lcm усіх чисел у масиві args. Другий параметр num- це підрахунок чисел у масиві.

Покладіть всі ці числа в масив, argsа потім викликайте функцію типуlcm_n(args,num);

Ця функція повертає lcm усіх цих чисел.

Ось реалізація функції 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);
    }
}

Для роботи цієї функції потрібно нижче двох функцій. Отже, просто додайте їх разом із цим.

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

У пітоні:

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

Це те, що я використав -

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

У Ruby це так просто, як:

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

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

(випробувано на Ruby 2.2.10 та 2.6.3.)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.