Наименьший общий множитель для 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
Оооо, учебник рекурсии :)
Питер Воне
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)
JFS
источник
1
Я не знаком с Python, что делает Reduce ()?
паан
17
Для заданной функции f и списка l = [a, b, c, d], Reduce (f, l) возвращает f (f (f (a, b), c), d). Это функциональная реализация «lcm может быть вычислена путем итеративного вычисления lcm текущего значения и следующего элемента списка».
А. Рекс
4
+1 за показ решения, которое можно адаптировать к более чем трем параметрам
OnesimusUnbound
Вы можете заставить функцию lcm вести себя как функция lcmm, уменьшая себя? Моя первая мысль - сделать так, чтобы он выполнял lcm (), когда есть 2 аргумента, и выполнял Reduce (), когда их больше.
эндолит
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));
    }
}
T3db0t
источник
2
Плохо, что я не понимаю, что вы подразумеваете под "стилем ECMA" = /
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);
}

Просто некоторые пояснения, потому что на первый взгляд это не так ясно, что делает этот код:

Aggregate - это метод Linq Extension, поэтому вы не можете забыть добавить с помощью System.Linq к своим ссылкам.

Агрегат получает функцию накопления, поэтому мы можем использовать свойство lcm (a, b, c) = lcm (a, lcm (b, c)) над IEnumerable. Подробнее о совокупности

Расчет 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функцию, только чтобы найти ее в Prelude! У меня сегодня много учений: 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;
    }
}'
t9mike
источник
3

Функция для нахождения lcm любого списка номеров:

 def function(l):
     s = 1
     for i in l:
        s = lcm(i, s)
     return s
Аадитя Мишра
источник
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;и не забывать обрабатывать исключения ...

SepehrM
источник
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)
Zach-M
источник
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) }
}
cmilr
источник
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
mpalanco
источник
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));
}
Saebekassebil
источник
1
Вы вызвали, gcd(a, b)но gdcфункция ожидает массив, поэтому вы хотели вызватьgcd([a, b])
João Pinto Jerónimo
это самый элегантный ответ на сегодняшний день
Lokua
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 (а, б, в) = LCM (LCM (а, б), в) = LCM (а, LCM (б, в))

Вот пример кода на 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. Все числа находятся внутри вектора 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 
Доктор медицинских наук Нашид Анжум
источник
Код ценится, но если вы можете добавить комментарии, подробно описывающие, как он работает, он ценится еще больше.
Алекс Райли
Хотя этот фрагмент кода может решить вопрос, в том числе объяснение действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос для читателей в будущем, а не только для того, кто спрашивает сейчас! Пожалуйста, отредактируйте свой ответ, чтобы добавить объяснение и указать, какие ограничения и предположения применяются.
Тоби Спейт
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; }

Vipul
источник
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

для питона 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

В Ruby это так просто:

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

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

(протестировано на Ruby 2.2.10 и 2.6.3.)

Хосам Али
источник