3 veya daha fazla sayı için en az ortak kat


152

Birden çok sayının en az ortak katını nasıl hesaplarsınız?

Şimdiye kadar sadece iki sayı arasında hesaplayabildim. Ancak 3 veya daha fazla sayıyı hesaplamak için nasıl genişleteceğiniz hakkında hiçbir fikriniz yok.

Şimdiye kadar böyle yaptım

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

Gcd ile sayılar için en büyük ortak böleni hesaplama işlevidir. Öklid algoritmasını kullanma

Ama 3 veya daha fazla sayı için nasıl hesaplayacağımı anlayamıyorum.


74
lütfen bunu ev ödevi olarak etiketleme. Birden fazla metal levhayı bir tabağa sığdırmanın bir yolunu bulmaya çalışıyorum ve aynı plaka üzerine farklı uzunlukta metalleri sığdırmanın bir yolunu bulmam gerekiyor. LCM ve GCD bunu yapmanın en iyi yoludur. Ben matematikçi değil programcıyım. Bu yüzden sordum.
paan

2
Küçük sayfaları daha büyük bir sayfaya yerleştirme - 2D kutu ambalajı?
Yüksek Performanslı Mark

3
@HighPerformanceMark Tetris?
mbomb007

Yanıtlar:


181

İki sayının LCM'sini yinelemeli olarak hesaplayarak, ikiden fazla sayının LCM'sini, yani

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

10
Ooooh ders kitabı özyineleme :)
Peter Wone

10
özyinelemeli algoritma tanımı zorunlu olarak özyinelemeli bir alt program anlamına gelmez. Bunu bir döngüde oldukça basit bir şekilde uygulayabilirsiniz. Mükemmel cevap için teşekkürler.
Marius

144

Python'da (değiştirilmiş 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)

Kullanımı:

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

reduce()Şöyle çalışır o :

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

1
Python'a aşina değilim, reduce () ne yapar?
paan

17
F işlevi ve l = [a, b, c, d] listesi verildiğinde, azalma (f, l), f (f (f (a, b), c), d) döndürür. "Lcm, geçerli değerin lcm'ini ve listenin bir sonraki öğesini yinelemeli olarak hesaplayarak hesaplanabilir."
A. Rex

4
Üç parametreden daha fazlasına uyum sağlayabilen bir çözüm göstermek için +1
OnesimusUnbound

lcm işlevinin kendisini azaltarak lcmm işlevi gibi davranmasını sağlayabilir misiniz? İlk düşüncem 2 argüman olduğunda lcm () 'i yapmak ve daha fazlası olduğunda reduce ()' yi yapmaktır.
endolith

1
@Kıllı virgül Python'da bir grup oluşturur. Bu durumda, şuna eşittir:t = a; a = b; b = t % b
jfs

26

İşte ECMA tarzı bir uygulama:

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

Ben bununla (C #) giderdim:

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);
}

Sadece bazı açıklamalar, çünkü ilk bakışta bu kodun ne yaptığını o kadar netleştirmiyor:

Aggregate bir Linq Extension yöntemidir, bu nedenle referanslarınıza System.Linq kullanarak eklemeyi unutamazsınız.

Agrega biriktirme işlevi görür, böylece IEnumerable üzerinden lcm (a, b, c) = lcm (a, lcm (b, c)) özelliğini kullanabiliriz. Aggregate hakkında daha fazlası

GCD hesaplaması Öklid algoritmasını kullanır .

lcm hesaplamasında Abs (a * b) / gcd (a, b) kullanılır, bkz. En büyük ortak bölenle azaltma .

Bu yardımcı olur umarım,


6

Haskell'de bunu anladım:

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

Hatta kendi gcdfonksiyonumu yazmak için zaman ayırdım, sadece Prelude'da bulmak için! Bugün benim için çok şey öğreniyorum: D


1
Son satır için foldr1 kullanabilirsiniz: lcm ns = foldr1 lcm' nsveyalcm = foldr1 lcm'
Neil Mayhew

Ayrıca Integral, ima ettiği gibi , gerçekten en az sonuç için, tip imzalardan da vazgeçebilirsinizdiv
Neil Mayhew

6

Gcd için bir işlev gerektirmeyen bazı Python kodları:

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)

Terminalde şöyle görünüyor:

$ python lcm.py 10 15 17
510

6

İşte tamsayıların LCM'sini 1'den 20'ye dahil etmek için bir Python tek astarlı (ithalat saymaz):

Python 3.5+ ithalatı:

from functools import reduce
from math import gcd

Python 2.7 ithalatı:

from fractions import gcd

Ortak mantık:

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

Hem o Not Python 2 ve Python 3 , operatör öncelik kuralları dikte *ve //operatörlerin aynı önceliğe sahiptir ve bunlar itibaren uygulanır böylece soldan sağa. Gibi, x*y // zanlamına gelir (x*y) // zve değil x * (y//z). İkisi tipik olarak farklı sonuçlar verir. Bu şamandıra bölümü için önemli değildir, ancak zemin bölümü için de önemlidir .


3

İşte Virgil Disgr4ce uygulamasının bir C # portu:

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

Herhangi bir sayı listesinin lcm'ini bulma işlevi:

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

2

LINQ kullanarak şunları yazabilirsiniz:

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;İstisnaları eklemeli ve bunlarla başa çıkmayı unutmamalı ...


2

Ve Scala versiyonu:

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

İşte Swift'te .

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

başka bir yolla yapabilirsiniz - n sayı olsun. bir çift ardışık sayı alın ve lcm başka bir dizide kaydedin. Bunu ilk yineleme programında yapmak n / 2 yinelemesi yapar. Ardından 0 (0,1), (2,3) vb. Seviyeden başlayarak çifti toplayın. LCM'lerini hesaplayın ve başka bir dizide saklayın. Bunu bir dizi bırakana kadar yapın. (n tekse lcm bulmak mümkün değildir)


1

R'de, x tamsayı vektöründeki tüm sayılar için en büyük ortak böleni ve en az ortak katlamayı hesaplamak için paket numaralarından mGCD (x) ve mLCM (x) fonksiyonlarını kullanabiliriz :

    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 tarzı

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
Aradınız, gcd(a, b)ancak gdcişlev bir dizi bekliyor, bu yüzden aramak gcd([a, b])
istediniz

Bu en zarif cevap
Lokua

1

Sadece eğlence için bir kabuk (hemen hemen her kabuk) uygulaması:

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

ile deneyin:

$ ./script 2 3 4 5 6

almak

60

En büyük girdi ve sonuç küçüktür (2^63)-1veya kabuk matematiği sarılır.


1

dizi öğelerinin gcd ve lcm arıyordu ve aşağıdaki bağlantıda iyi bir çözüm buldum.

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

Aşağıdaki kodu içerir. Gcd algoritması Öklid Algoritması, aşağıdaki bağlantıda iyi açıklanmıştır.

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

İşte PHP uygulaması:

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

Krediler yukarıdaki cevabı ile @ T3db0t (ECMA tarzı kod) .


0

GCD'nin negatif sayılar için küçük bir düzeltmeye ihtiyacı vardır:

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

Buna ne dersin?

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

Calculla'da En Az Ortak Çoklu Katmanın , aynı zamanda adımları gösteren herhangi bir sayıda girdi için çalışan çalışma uygulamamız var .

Yaptığımız şey:

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.

Ve işte bu - cm'nizi aldınız.


0

LCM hem birleştirici hem de değişmeli.

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

burada örnek kod 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 yöntemi bir vektörü alır ve LCM'yi döndürür. Tüm sayılar vektör_sayısı dahilindedir.

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 takdir edilir, ancak nasıl çalıştığını açıklayan yorumlar ekleyebilirseniz daha da takdir edilir.
Alex Riley

Bu kod snippet'i soruyu çözebilir, ancak bir açıklama da dahil olmak üzere , yayınınızın kalitesini artırmaya yardımcı olur . Sadece şu anda soran kişi için değil, gelecekte okuyucular için soruyu cevapladığınızı unutmayın! Lütfen açıklama eklemek için cevabınızı düzenleyin ve hangi sınırlamaların ve varsayımların geçerli olduğunu belirtin.
Toby Speight

0

Hızlı çalışma kodu arayan herkes için şunu deneyin:

lcm_n(args, num) Dizideki tüm sayıların lcm değerini hesaplayan ve döndüren bir işlev yazdım args. İkinci parametre numdizideki sayıların sayısıdır.

Tüm bu sayıları bir diziye koyun argsve sonra işlevi şöyle çağırınlcm_n(args,num);

Bu işlev tüm bu sayıların lcm'ini döndürür .

İşte işlevin uygulanması 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);
    }
}

Bu fonksiyonun çalışması için iki fonksiyonun altında olması gerekir. Yani, sadece onları ekleyin.

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

Python'da:

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

Kullandığım şey bu -

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

python 3 için:

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'de bu kadar basit:

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

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

(Ruby 2.2.10 ve 2.6.3'te test edilmiştir.)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.