जावा: सबसे बड़ा सामान्य विभाजक मिलता है


91

मैंने देखा है कि इस तरह के एक समारोह के लिए मौजूद है BigInteger, यानी BigInteger#gcd। क्या जावा में अन्य कार्य हैं जो अन्य प्रकारों ( int, longया Integer) के लिए भी काम करते हैं ? ऐसा लगता है कि यह java.lang.Math.gcd(सभी प्रकार के अधिभार के साथ) समझ में आएगा, लेकिन ऐसा नहीं है। यह कहीं और है?


(इस सवाल को भ्रमित न करें कि "मैं इसे कैसे लागू करूं", कृपया!)


7
क्यों स्वीकार किया गया उत्तर एक है जो आपको बताता है कि इसे कैसे लागू किया जाए - हालांकि मौजूदा कार्यान्वयन को लपेटकर? =)
djjeck

मैं आपके अवलोकन से सहमत हूं। जीसीडी को ओवरलोडेड स्टैटिक विधियों के एक समूह के साथ एक वर्ग होना चाहिए जो दो नंबरों में लेता है और इसे एलसीडी देता है। और यह java.math पैकेज का हिस्सा होना चाहिए।
अनु

जवाबों:


79

आदिम और लंबे समय के लिए, आदिम के रूप में, वास्तव में नहीं। इंटेगर के लिए, यह संभव है कि किसी ने एक लिखा हो।

यह देखते हुए कि BigInteger int, Integer, long, और Long का एक (गणितीय / कार्यात्मक) सुपरसेट है, यदि आपको इन प्रकारों का उपयोग करने की आवश्यकता है, तो उन्हें BigInteger में कनवर्ट करें, GCD करें, और परिणाम को वापस बदलें।

private static int gcdThing(int a, int b) {
    BigInteger b1 = BigInteger.valueOf(a);
    BigInteger b2 = BigInteger.valueOf(b);
    BigInteger gcd = b1.gcd(b2);
    return gcd.intValue();
}

63
BigInteger.valueOf(a).gcd(BigInteger.valueOf(b)).intValue()ज़्यादा बेहतर है।
अल्बर्ट


4
अगर इस फ़ंक्शन को अक्सर (यानी लाखों बार) कहा जाता है, तो आपको इंट या बिगइंटर को लंबे समय तक परिवर्तित नहीं करना चाहिए। केवल आदिम मूल्यों का उपयोग करने वाला एक कार्य संभवत: तीव्रता का क्रम होगा। अन्य उत्तरों की जाँच करें।
jcsahnwaldt

@ भानु प्रताप सिंह कास्टिंग या छंटनी से बचने के लिए, अंतर और लंबे समय के लिए अलग-अलग तरीकों का उपयोग करना बेहतर है। मैंने तदनुसार उत्तर संपादित किया।
jcsahnwaldt

1
यह न केवल सवाल का जवाब देता है (जहां जावा में int या लंबे समय के लिए gcd है), लेकिन प्रस्तावित कार्यान्वयन बहुत ही अक्षम है। यह स्वीकृत उत्तर नहीं होना चाहिए। जहां तक ​​मुझे पता है जावा रनटाइम में यह नहीं है, लेकिन यह तीसरे पक्ष के पुस्तकालयों में मौजूद है।
फ्लोरियन एफ

134

जहाँ तक मुझे पता है, आदिम के लिए कोई अंतर्निहित पद्धति नहीं है। लेकिन कुछ सरल के रूप में इस चाल करना चाहिए:

public int gcd(int a, int b) {
   if (b==0) return a;
   return gcd(b,a%b);
}

यदि आप उस प्रकार की चीज़ में हैं, तो आप इसे एक-पंक्ति में भी कर सकते हैं:

public int gcd(int a, int b) { return b==0 ? a : gcd(b, a%b); }

यह ध्यान दिया जाना चाहिए कि दोनों के बीच बिल्कुल कोई अंतर नहीं है क्योंकि वे एक ही बाइट कोड को संकलित करते हैं।


जहां तक ​​मैं बता सकता हूं कि यह ठीक काम करता है। मैं सिर्फ 100,000 यादृच्छिक संख्या चलाता था, हालांकि दोनों विधियां और वे हर बार सहमत थे।
टोनी एननिस

19
यह यूक्लिडियन एल्गोरिथ्म है ... यह बहुत पुराना और सही साबित हुआ है। en.wikipedia.org/wiki/Euclidean_algorithm
रेकिन

हां, मैं इसे देख सकता हूं लेकिन मुझे इसके माध्यम से काम करने के लिए अधिक समय चाहिए। मुझें यह पसंद है।
टोनी एननिस

1
@ अल्बर्ट, अच्छी तरह से आप इसे हमेशा एक सामान्य प्रकार के साथ आज़मा सकते हैं और देखें कि क्या यह काम करता है। मुझे सिर्फ एक विचार नहीं है, लेकिन आपके साथ प्रयोग करने के लिए एल्गोरिथ्म है। जहाँ तक कुछ मानक पुस्तकालय या कक्षा है, मैंने कभी नहीं देखा है। आपको तब भी निर्दिष्ट करना होगा जब आप ऑब्जेक्ट बनाते हैं कि यह एक int, long आदि है। हालांकि।
मैट

1
@ अल्बर्ट, ठीक है, हालांकि मैट ने एक कार्यान्वयन प्रदान किया, आप स्वयं इसे एक काम कर सकते हैं, जैसा कि आप कहते हैं, "अधिक सामान्य" तरीका है, नहीं? :)
बार्टर्स कीर्स

33

या जीसीडी की गणना के लिए यूक्लिडियन एल्गोरिथ्म ...

public int egcd(int a, int b) {
    if (a == 0)
        return b;

    while (b != 0) {
        if (a > b)
            a = a - b;
        else
            b = b - a;
    }

    return a;
}

3
बस स्पष्ट करने के लिए: यह बिल्कुल वैसा नहीं है जैसा मैं पूछ रहा था।
अल्बर्ट

11
इस स्थिति में, आपने निर्दिष्ट नहीं किया था कि आप वैकल्पिक कार्यान्वयन नहीं चाहते थे क्योंकि कोई मौजूद नहीं था। केवल बाद में आपने अपना पोस्ट संपादित किया जो कार्यान्वयन के लिए नहीं लग रहा था। मेरा मानना ​​है कि दूसरों ने पर्याप्त रूप से "नहीं" का जवाब दिया था।
Xorlev

2
यह धीमा होगा यदि a बहुत बड़ा है और b छोटा है। '%' समाधान ज्यादा तेज होगा।
ब्रूस फेइस्ट

12

अमरूद का उपयोग करें LongMath.gcd()औरIntMath.gcd()


2
दिलचस्प है कि अमरूद यूक्लिडियन "मोडुलो" पद्धति का उपयोग नहीं करता है लेकिन बाइनरी जीसीडी एल्गोरिथ्म है कि वे 40% तेज होने का दावा करते हैं। यह कहना बहुत सुरक्षित है कि यह काफी कुशल और अच्छी तरह से परखा हुआ है।
फ्लोरियन एफ

12

जब तक मेरे पास अमरूद नहीं है, मैं इस तरह से परिभाषित करता हूं:

int gcd(int a, int b) {
  return a == 0 ? b : gcd(b % a, a);
}


7

आप बाइनरी जीसीडी एल्गोरिथ्म के इस कार्यान्वयन का उपयोग कर सकते हैं

public class BinaryGCD {

public static int gcd(int p, int q) {
    if (q == 0) return p;
    if (p == 0) return q;

    // p and q even
    if ((p & 1) == 0 && (q & 1) == 0) return gcd(p >> 1, q >> 1) << 1;

    // p is even, q is odd
    else if ((p & 1) == 0) return gcd(p >> 1, q);

    // p is odd, q is even
    else if ((q & 1) == 0) return gcd(p, q >> 1);

    // p and q odd, p >= q
    else if (p >= q) return gcd((p-q) >> 1, q);

    // p and q odd, p < q
    else return gcd(p, (q-p) >> 1);
}

public static void main(String[] args) {
    int p = Integer.parseInt(args[0]);
    int q = Integer.parseInt(args[1]);
    System.out.println("gcd(" + p + ", " + q + ") = " + gcd(p, q));
}

}

से http://introcs.cs.princeton.edu/java/23recursion/BinaryGCD.java.html


यह स्टीन के एल्गोरिथ्म की भिन्नता है जो शोषण करता है कि ज्यादातर मशीनों पर, स्थानांतरण एक अपेक्षाकृत सस्ता ऑपरेशन है। यह एक मानक एल्गोरिथ्म है।
बैस्टियन जे

6

यहां कुछ कार्यान्वयन सही ढंग से काम नहीं कर रहे हैं यदि दोनों संख्याएं नकारात्मक हैं। gcd (-12, -18) 6 है, न कि -6।

तो एक निरपेक्ष मूल्य लौटाया जाना चाहिए, जैसे कुछ

public static int gcd(int a, int b) {
    if (b == 0) {
        return Math.abs(a);
    }
    return gcd(b, a % b);
}

इसका एक बढ़त मामले अगर दोनों है aऔर bकर रहे हैं Integer.MIN_VALUE, तो आप मिल जाएगा Integer.MIN_VALUEपरिणाम है, जो नकारात्मक है के रूप में वापस। यह स्वीकार्य हो सकता है। समस्या यह है कि gcd (-2 ^ 31, -2 ^ 31) = 2 ^ 31, लेकिन 2 ^ 31 को पूर्णांक के रूप में व्यक्त नहीं किया जा सकता है।
माइकल एंडरसन

मैं यह भी उपयोग if(a==0 || b==0) return Math.abs(a+b);करने की सलाह दूंगा ताकि व्यवहार शून्य तर्क के लिए वास्तव में सममित हो।
माइकल एंडरसन

3

हम gcd खोजने के लिए पुनरावर्ती कार्य का उपयोग कर सकते हैं

public class Test
{
 static int gcd(int a, int b)
    {
        // Everything divides 0 
        if (a == 0 || b == 0)
           return 0;

        // base case
        if (a == b)
            return a;

        // a is greater
        if (a > b)
            return gcd(a-b, b);
        return gcd(a, b-a);
    }

    // Driver method
    public static void main(String[] args) 
    {
        int a = 98, b = 56;
        System.out.println("GCD of " + a +" and " + b + " is " + gcd(a, b));
    }
}

2

यदि आप जावा 1.5 या उसके बाद का उपयोग कर रहे हैं तो यह एक पुनरावृत्त बाइनरी जीसीडी एल्गोरिथ्म है जो Integer.numberOfTrailingZeros()आवश्यक चेक और पुनरावृत्तियों की संख्या को कम करने के लिए उपयोग करता है।

public class Utils {
    public static final int gcd( int a, int b ){
        // Deal with the degenerate case where values are Integer.MIN_VALUE
        // since -Integer.MIN_VALUE = Integer.MAX_VALUE+1
        if ( a == Integer.MIN_VALUE )
        {
            if ( b == Integer.MIN_VALUE )
                throw new IllegalArgumentException( "gcd() is greater than Integer.MAX_VALUE" );
            return 1 << Integer.numberOfTrailingZeros( Math.abs(b) );
        }
        if ( b == Integer.MIN_VALUE )
            return 1 << Integer.numberOfTrailingZeros( Math.abs(a) );

        a = Math.abs(a);
        b = Math.abs(b);
        if ( a == 0 ) return b;
        if ( b == 0 ) return a;
        int factorsOfTwoInA = Integer.numberOfTrailingZeros(a),
            factorsOfTwoInB = Integer.numberOfTrailingZeros(b),
            commonFactorsOfTwo = Math.min(factorsOfTwoInA,factorsOfTwoInB);
        a >>= factorsOfTwoInA;
        b >>= factorsOfTwoInB;
        while(a != b){
            if ( a > b ) {
                a = (a - b);
                a >>= Integer.numberOfTrailingZeros( a );
            } else {
                b = (b - a);
                b >>= Integer.numberOfTrailingZeros( b );
            }
        }
        return a << commonFactorsOfTwo;
    }
}

अध्याय परीक्षा:

import java.math.BigInteger;
import org.junit.Test;
import static org.junit.Assert.*;

public class UtilsTest {
    @Test
    public void gcdUpToOneThousand(){
        for ( int x = -1000; x <= 1000; ++x )
            for ( int y = -1000; y <= 1000; ++y )
            {
                int gcd = Utils.gcd(x, y);
                int expected = BigInteger.valueOf(x).gcd(BigInteger.valueOf(y)).intValue();
                assertEquals( expected, gcd );
            }
    }

    @Test
    public void gcdMinValue(){
        for ( int x = 0; x < Integer.SIZE-1; x++ ){
            int gcd = Utils.gcd(Integer.MIN_VALUE,1<<x);
            int expected = BigInteger.valueOf(Integer.MIN_VALUE).gcd(BigInteger.valueOf(1<<x)).intValue();
            assertEquals( expected, gcd );
        }
    }
}

MutableBigInteger.binaryGcd (int, int) के समान, दुर्भाग्यवश उत्तरार्द्ध सुलभ नहीं है। लेकिन वैसे भी शांत!
मोस्टोव्स्की पतन

2
public int gcd(int num1, int num2) { 
    int max = Math.abs(num1);
    int min = Math.abs(num2);

    while (max > 0) {
        if (max < min) {
            int x = max;
            max = min;
            min = x;
        }
        max %= min;
    }

    return min;
}

यह विधि यूक्लिड के एल्गोरिथ्म का उपयोग करके दो पूर्णांकों का "सबसे बड़ा सामान्य विभाजक" प्राप्त करती है। यह दो पूर्णांक प्राप्त करता है और उनमें से gcd को लौटाता है। बस इतना आसान!


1

यह कहीं और है?

अमरीका की एक मूल जनजाति!- यह दोनों gcd और lcm है, इतना अच्छा है!

हालांकि, उनके कार्यान्वयन की गहनता के कारण, यह सरल हाथ से लिखे गए संस्करण (यदि यह मायने रखता है) की तुलना में धीमा है।


0
/*
import scanner and instantiate scanner class;
declare your method with two parameters
declare a third variable;
set condition;
swap the parameter values if condition is met;
set second conditon based on result of first condition;
divide and assign remainder to the third variable;
swap the result;
in the main method, allow for user input;
Call the method;

*/
public class gcf {
    public static void main (String[]args){//start of main method
        Scanner input = new Scanner (System.in);//allow for user input
        System.out.println("Please enter the first integer: ");//prompt
        int a = input.nextInt();//initial user input
        System.out.println("Please enter a second interger: ");//prompt
        int b = input.nextInt();//second user input


       Divide(a,b);//call method
    }
   public static void Divide(int a, int b) {//start of your method

    int temp;
    // making a greater than b
    if (b > a) {
         temp = a;
         a = b;
         b = temp;
    }

    while (b !=0) {
        // gcd of b and a%b
        temp = a%b;
        // always make a greater than b
        a =b;
        b =temp;

    }
    System.out.println(a);//print to console
  }
}

क्या आप इसकी व्याख्या कर सकते हैं कि यह कैसे मदद कर सकता है?
कोमराधोमोर

0

मैंने इस पद्धति का उपयोग किया था जिसे मैंने 14 साल की उम्र में बनाया था।

    public static int gcd (int a, int b) {
        int s = 1;
        int ia = Math.abs(a);//<-- turns to absolute value
        int ib = Math.abs(b);
        if (a == b) {
            s = a;
        }else {
            while (ib != ia) {
                if (ib > ia) {
                    s = ib - ia;
                    ib = s;
                }else { 
                    s = ia - ib;
                    ia = s;
                }
            }
        }
        return s;
    }

0

कॉमन्स-मठ और अमरूद द्वारा प्रदान किए गए जीसीडी कार्यों में कुछ अंतर हैं।

  • कॉमन्स-मैथ फेंकता है ArithematicException.class केवल Integer.MIN_VALUEया के लिएLong.MIN_VALUE
    • अन्यथा, मान को निरपेक्ष मान के रूप में संभालता है।
  • अमरूद IllegalArgumentException.classकिसी भी नकारात्मक मूल्यों के लिए फेंकता है ।

-3

% हमें दो संख्याओं के बीच की gcd देने वाला है, इसका अर्थ है: -% या mod_number / small_number = gcd है, और हम इसे जावा पर इस तरह लिखते हैं big_number % small_number

EX1: दो पूर्णांकों के लिए

  public static int gcd(int x1,int x2)
    {
        if(x1>x2)
        {
           if(x2!=0)
           {
               if(x1%x2==0)     
                   return x2;
                   return x1%x2;
                   }
           return x1;
           }
          else if(x1!=0)
          {
              if(x2%x1==0)
                  return x1;
                  return x2%x1;
                  }
        return x2;
        } 

EX2: तीन पूर्णांकों के लिए

public static int gcd(int x1,int x2,int x3)
{

    int m,t;
    if(x1>x2)
        t=x1;
    t=x2;
    if(t>x3)
        m=t;
    m=x3;
    for(int i=m;i>=1;i--)
    {
        if(x1%i==0 && x2%i==0 && x3%i==0)
        {
            return i;
        }
    }
    return 1;
}

2
यह गलत है, जैसे gcd(42, 30)होना चाहिए 6लेकिन यह 12आपके उदाहरण से है। लेकिन 12 30 का विभाजक नहीं है और न ही 42 का। आपको gcdपुनरावर्ती कॉल करना चाहिए । मैट द्वारा उत्तर देखें या यूक्लिडियन एल्गोरिथ्म के लिए विकिपीडिया पर देखें।
अल्बर्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.