জাভা: সর্বাধিক সাধারণ বিভাজক পান


91

আমি দেখেছি যে এই জাতীয় ফাংশনটি বিদ্যমান BigInteger, যেমন BigInteger#gcd। জাভাতে কি অন্যান্য ফাংশন রয়েছে যা অন্যান্য ধরণের ( int, longবা Integer) জন্যও কাজ করে ? দেখে মনে হচ্ছে এটি java.lang.Math.gcd(সমস্ত ধরণের ওভারলোডের সাথে) এর মতো হবে তবে এটি সেখানে নেই। এটা অন্য কোথাও?


("আমি কীভাবে এটি নিজেকে বাস্তবায়ন করব" দিয়ে এই প্রশ্নটিকে বিভ্রান্ত করবেন না, দয়া করে!)


7
কোনও বিদ্যমান বাস্তবায়ন মোড়ক দেওয়ার পরেও কীভাবে গৃহীত উত্তরটি আপনাকে তা প্রয়োগ করতে হয় তা বলবে? =)
ডিজেজেক

আমি আপনার পর্যবেক্ষণের সাথে একমত জিসিডির একটি শ্রেণীর ওভারলোড হওয়া স্থির পদ্ধতিগুলির একটি গোছা হওয়া উচিত যা দুটি সংখ্যায় লাগে এবং এটিকে জিসিডি দেয়। এবং এটি java.math প্যাকেজের অংশ হওয়া উচিত।
আনু

উত্তর:


81

আদি এবং দীর্ঘ সময়ের জন্য, আদিম হিসাবে, সত্যই নয়। পূর্ণসংখ্যার জন্য, এটি সম্ভবত কেউ লিখেছেন।

বিগইন্টেগার হ'ল একটি (গাণিতিক / ক্রিয়ামূলক) ইনট, ইন্টিজার, লম্বা এবং লম্বের সুপারসেট, যদি আপনাকে এই ধরণের ব্যবহারের প্রয়োজন হয় তবে সেগুলি একটি বিগইন্টিজারে রূপান্তর করুন, জিসিডি করুন, এবং ফলাফলটি আবার রূপান্তর করুন।

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

65
BigInteger.valueOf(a).gcd(BigInteger.valueOf(b)).intValue()অনেক ভাল।
অ্যালবার্ট


4
যদি এই ফাংশনটি প্রায়শই বলা হয় (অর্থাত্ লক্ষ লক্ষ বার) আপনার অবধি বা দীর্ঘকে বিগইন্টিজারে রূপান্তর করা উচিত নয়। শুধুমাত্র আদিম মানগুলি ব্যবহার করে একটি ফাংশন সম্ভবত দ্রুততার একটি ক্রম হবে। অন্যান্য উত্তরগুলি পরীক্ষা করুন।
জেসিএসাহ্নওয়াল্ড্ট মনিকা

@ ভানু প্রতাপ সিং কাস্টিং বা কাটছাঁটি এড়ানোর জন্য, দীর্ঘ এবং দীর্ঘ সময়ের জন্য পৃথক পদ্ধতি ব্যবহার করা ভাল। আমি সেই অনুযায়ী উত্তরটি সম্পাদনা করেছি।
জেসিএসাহ্নওয়াল্ড্ট মনিকা

4
এটি কেবল প্রশ্নের উত্তর দেয় না (যেখানে জিএসডি ইনট বা জাভাতে দীর্ঘ হবে) তবে প্রস্তাবিত প্রয়োগটি বেশ অপ্রতুল। এটি গ্রহণযোগ্য উত্তর হওয়া উচিত নয়। আমি যতদূর জানি জাভা রানটাইমের এটি নেই তবে এটি তৃতীয় পক্ষের লাইব্রেরিতে রয়েছে।
ফ্লোরিয়ান এফ

135

আমি যতদূর জানি, আদিমদের জন্য কোনও বিল্ট-ইন পদ্ধতি নেই। তবে এর মতো সহজ কিছুতে কৌশলটি করা উচিত:

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 এলোমেলো সংখ্যা দৌড়েছি যদিও উভয় পদ্ধতিই এবং তারা প্রতিবার সম্মতি জানায়।
টনি এনিস

20
এটি ইউক্লিডিয়ান অ্যালগরিদম ... এটি খুব পুরানো এবং সঠিক প্রমাণিত। en.wikipedia.org/wiki/Euclidean_algorithm
Rekin

হ্যাঁ, আমি এটিকে দেখতে চাই তবে এটির মাধ্যমে কাজ করার জন্য আমার আরও সময় প্রয়োজন। আমি এটা পছন্দ করি.
টনি এনিস

4
@ অ্যালবার্ট, ভাল আপনি সবসময় জেনেরিক ধরণের মাধ্যমে চেষ্টা করে দেখতে পারেন এবং এটি কার্যকর কিনা তা দেখতে পারেন। আমি কেবল একটি চিন্তাকেই জানি না, তবে অ্যালগরিদম আপনার সাথে পরীক্ষা করার জন্য রয়েছে। কিছু স্ট্যান্ডার্ড গ্রন্থাগার বা ক্লাস হিসাবে, আমি কখনও একটি দেখেনি। আপনি এখনও যখন অবজেক্টটি তৈরি করবেন তখন এটি নির্দিষ্ট করতে হবে যে এটি কোনও পূর্ববর্তী, দীর্ঘ ইত্যাদি though
ম্যাট 18

4
@ অ্যালবার্ট, আচ্ছা, যদিও ম্যাট একটি বাস্তবায়ন সরবরাহ করেছে, আপনি নিজে যেমন এটি "আরও জেনেরিক" উপায়ে বলেছেন, না? :)
বার্ট কায়ার্স

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

4
কেবল স্পষ্ট করে বলতে: এটি আমি যা চেয়েছিলাম তা একেবারেই নয়।
অ্যালবার্ট

11
এই ক্ষেত্রে, আপনি নির্দিষ্ট করে থাকেননি যে বিকল্পের বাস্তবায়ন চান না কারণ একটি বিদ্যমান নেই one কেবলমাত্র পরে আপনি নিজের পোস্ট সম্পাদনা করে বাস্তবায়নগুলি খুঁজছেন না। আমি বিশ্বাস করি যে অন্যরা পর্যাপ্ত পরিমাণের চেয়ে "না" জবাব দিয়েছিল।
জোরলেভ

4
এটি ধীর হবে যদি একটি খুব বড় এবং খ ছোট হয়। '%' সমাধানগুলি আরও দ্রুত হবে।
ব্রুস ফিস্ট 21

12

পেয়ারা LongMath.gcd()এবং ব্যবহার করুনIntMath.gcd()


4
মজার বিষয় হল পেয়ারা ইউক্যালিডিয়ান "মডুলো" পদ্ধতি ব্যবহার করে না তবে বাইনারি জিসিডি অ্যালগরিদম যে তারা দাবি করে 40% দ্রুত be এটি বেশ দক্ষ এবং ভালভাবে পরীক্ষা করা বলা নিরাপদ।
ফ্লোরিয়ান এফ

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

উভয় সংখ্যা negativeণাত্মক হলে এখানে কিছু বাস্তবায়ন সঠিকভাবে কাজ করছে না। জিসিডি (-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ফলাফলের, যা নেতিবাচক হিসাবে ফিরে। এটি গ্রহণযোগ্য হতে পারে। সমস্যাটি যে সিসিডি (-2 ^ 31, -2 ^ 31) = 2 ^ 31, তবে 2 ^ 31 হিসাবে পূর্ণসংখ্যা হিসাবে প্রকাশ করা যায় না।
মাইকেল অ্যান্ডারসন

আমি ব্যবহার if(a==0 || b==0) return Math.abs(a+b);করার পরামর্শ দিই যাতে আচরণটি শূন্য আর্গুমেন্টের জন্য সত্যই প্রতিসাম্যপূর্ণ হয়।
মাইকেল অ্যান্ডারসন

3

আমরা জিসিডি সন্ধানের জন্য পুনরাবৃত্ত ফাংশন ব্যবহার করতে পারি

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

এই পদ্ধতিটি ইউক্লিডের অ্যালগরিদম ব্যবহার করে দুটি পূর্ণসংখ্যার "গ্রেটেস্ট সাধারণ সাধারণ বিভাজক" পেতে। এটি দুটি পূর্ণসংখ্যা গ্রহণ করে এবং এরগুলির জিসিডি প্রদান করে। শুধু যে সহজ!


1

এটা অন্য কোথাও?

আপাচে! - এটিতে জিসিডি এবং এলসিএম উভয়ই রয়েছে তাই দুর্দান্ত!

যাইহোক, তাদের বাস্তবায়নের গভীরতার কারণে, সরল হাতে লিখিত সংস্করণের সাথে তুলনায় এটি ধীরে ধীরে (যদি এটি বিবেচনা করে)।


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

এটি কীভাবে সহায়তা করতে পারে তার ব্যাখ্যা দিয়ে আপনি কী ব্যাখ্যা করতে পারেন?
kommradHomer

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

% দুটি সংখ্যার মধ্যে আমাদের জিসিডি দিচ্ছে, এর অর্থ: -% বা বড়_নম্বার / ছোট_ সংখ্যাটির মোড = জিসিডি, এবং আমরা এটি জাভাতে লিখি 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;
}

4
এটি ভুল, উদাহরণস্বরূপ gcd(42, 30)হওয়া উচিত 6তবে এটি 12আপনার উদাহরণ দিয়ে। তবে 12 টি 30 এবং কোনোটাই 62 এর বিভাজক নয় You আপনার gcdপুনরাবৃত্তভাবে কল করা উচিত should ম্যাট দ্বারা উত্তর দেখুন বা ইউক্যালিডিয়ান অ্যালগরিদমের জন্য উইকিপিডিয়ায় দেখুন।
অ্যালবার্ট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.