জিসিডির জন্য সবচেয়ে দক্ষ কী?


26

আমি জানি যে ইউক্লিডের অ্যালগরিদম হ'ল ধনাত্মক পূর্ণসংখ্যার তালিকার জিসিডি (দুর্দান্ত সাধারণ বিভাজক) পাওয়ার জন্য সেরা অ্যালগরিদম। তবে অনুশীলনে আপনি এই অ্যালগরিদমকে বিভিন্ন উপায়ে কোড করতে পারেন। (আমার ক্ষেত্রে, আমি জাভা ব্যবহার করার সিদ্ধান্ত নিয়েছি, তবে সি / সি ++ অন্য বিকল্প হতে পারে)।

আমার প্রোগ্রামে আমার সবচেয়ে কার্যকর কোডটি ব্যবহার করা দরকার।

পুনরাবৃত্ত মোডে, আপনি লিখতে পারেন:

static long gcd (long a, long b){
    a = Math.abs(a); b = Math.abs(b);
    return (b==0) ? a : gcd(b, a%b);
  }

এবং পুনরাবৃত্তি মোডে, এটি দেখতে এটির মতো দেখাচ্ছে:

static long gcd (long a, long b) {
  long r, i;
  while(b!=0){
    r = a % b;
    a = b;
    b = r;
  }
  return a;
}

জিসিডির জন্য বাইনারি অ্যালগরিদমও রয়েছে, যা কেবল এভাবে কোড করা যেতে পারে:

int gcd (int a, int b)
{
    while(b) b ^= a ^= b ^= a %= b;
    return a;
}

3
আমি মনে করি এটি খুব সাবজেক্টিভ এবং স্ট্যাকওভারফ্লোয়ের জন্য সম্ভবত এটি আরও ভাল suited "অনুশীলনে সর্বাধিক দক্ষ" অনেকগুলি (এমনকি অপ্রত্যাশিত) কারণগুলির উপর নির্ভর করে যেমন অন্তর্নিহিত আর্কিটেকচার, মেমরি শ্রেণিবদ্ধতা, আকার এবং
ইনপুটটির

5
এটি একই অ্যালগরিদমটি পুনরাবৃত্ত এবং পুনরাবৃত্ত উপায়ে প্রকাশ করা হয়। আমি মনে করি ইউক্লিড অ্যালগরিদম বেশ দ্রুত রূপান্তরিত হওয়ায় তাদের পার্থক্য নগণ্য। আপনার পছন্দ অনুসারে এমন একটি চয়ন করুন।
প্যাড

6
আপনি এই দু'টিকে প্রোফাইল করার চেষ্টা করতে পারেন। যেহেতু রিকার্সিভ ভার্সনটি একটি লেজ কল, তাই সংকলকটি প্রায় একই কোডটি নির্গত করার সম্ভাবনা নেই।
লুই 18

1
এটা ভুল. খ! = 0 এর পরে হওয়া উচিত এবং তারপরে একটি ফিরে আসুন। অন্যথায় এটি শূন্য দ্বারা বিভাগে আউট আউট। আপনার যদি সত্যিই বড় গিসিডি থাকে তবে পুনরাবৃত্তিটি ব্যবহার করবেন না .... আপনি স্ট্যাক এবং ফাংশন স্টাইলের একটি স্তূপ পান ... কেন কেবল পুনরাবৃত্তি হবে না?
ক্রিস স্ট্রিংফেলো

4
নোট করুন যে সেখানে অসম্পূর্ণভাবে দ্রুত গিসিটি অ্যালগরিদম রয়েছে। উদাহরণস্বরূপ en.wikedia.org/wiki/Binary_GCD_algorithm
নিল ইয়ং

উত্তর:


21

আপনার দুটি অ্যালগরিদম সমতুল্য (কমপক্ষে ইতিবাচক পূর্ণসংখ্যার জন্য, অপরিহার্য সংস্করণে নেতিবাচক পূর্ণসংখ্যার সাথে কী ঘটে তা জাভার শব্দার্থবিজ্ঞানের উপর নির্ভর করে %যার জন্য আমি হৃদয় দিয়ে জানি না)। রিকার্সিভ সংস্করণে, দিন এবং আমি আর্গুমেন্ট হতে আমি তম recursive কল: একটি আমি + + 1 = আমি আমি + + 1 = একটি আমি মি আমিaibii

ai+1=bibi+1=aimodbi

অনুজ্ঞাসূচক সংস্করণে, দিন এবং ' আমি ভেরিয়েবলের মান হতে এবং শুরুতে আমি লুপের তম পুনরাবৃত্তির। a i + 1 = b i b i + 1 = a i m o d b iaibiabi

ai+1=bibi+1=aimodbi

একটি সাদৃশ্য লক্ষ্য? আপনার অপরিহার্য সংস্করণ এবং আপনার পুনরাবৃত্ত সংস্করণ হুবহু একই মান গণনা করা হয়। উপরন্তু, তারা একই সময়ে উভয় শেষ, যখন (রেস্প। একটি ' আমি = 0 ), তাই তারা পুনরাবৃত্তিও একই সংখ্যক সঞ্চালন। সুতরাং অ্যালগরিদমভাবে বলতে গেলে দুজনের মধ্যে কোনও পার্থক্য নেই। যে কোনও পার্থক্য বাস্তবায়নের বিষয় হবে, সংকলকটির উপর নির্ভরশীল, এটি যে হার্ডওয়্যারটি চালায় এবং সম্ভবত অপারেটিং সিস্টেম এবং অন্যান্য প্রোগ্রামগুলি একই সাথে চলছে।ai=0ai=0

রিকার্সিভ ভার্সনটি কেবল লেজ পুনরাবৃত্ত কল করে । অপরিহার্য ভাষার জন্য বেশিরভাগ সংকলক এগুলি অনুকূল করে না এবং তাই সম্ভবত তারা তৈরি কোডটি প্রতিটি পুনরাবৃত্তিতে স্ট্যাক ফ্রেম তৈরি করতে কিছুটা সময় এবং মেমোরি নষ্ট করবে। একটি সংকলক যা লেজ কলগুলি অনুকূল করে (প্রায়শই কার্যকরী ভাষাগুলির সংকলকগুলি করে), উত্পন্ন মেশিন কোড উভয়ের পক্ষে একই রকম হতে পারে (ধরে নিলে আপনি সেই কলগুলিকে একত্রিত করেছেন abs)।


8

যে সংখ্যাগুলি ছোট, বাইনারি জিসিডি অ্যালগরিদম যথেষ্ট।

GMP, একটি ভাল রক্ষণাবেক্ষণ করা এবং বাস্তব-বিশ্বের পরীক্ষিত লাইব্রেরি, লেহারের অ্যালগরিদমের একটি সাধারণীকরণ একটি বিশেষ প্রান্তিকতা পেরোনোর ​​পরে একটি বিশেষ অর্ধেক জিসিডি অ্যালগরিদমে স্যুইচ করবে। লেহমের স্ট্যান্ডার্ড ইউক্লিডিয়ান অ্যালগোরিদমকে উন্নত করতে ম্যাট্রিক্স গুণকে ব্যবহার করে। ডক্স অনুসারে, এইচজিসিডি এবং জিসিডি উভয়ের অ্যাসিম্পটোটিক চলমান সময় O(M(N)*log(N)), যেখানে M(N)দুটি এন-অঙ্গ সংখ্যার গুণনের সময় রয়েছে ।

তাদের অ্যালগরিদমের পুরো বিশদ এখানে পাওয়া যাবে


লিঙ্কটি সত্যই পুরো বিশদ সরবরাহ করে না এবং এমনকি একটি "অঙ্গ" কী তা নির্ধারণ করে না ...
আইনপোকলম - মনিকা


2

আমি জানি যে জাভা সাধারণত টেল রিকার্সন অপটিমাইজেশন সমর্থন করে না, তবে আপনি এর জন্য আপনার জাভা বাস্তবায়ন পরীক্ষা করতে পারেন; যদি এটি সমর্থন করে না, একটি সাধারণ- forলুপটি দ্রুত হওয়া উচিত, অন্যথায় পুনরাবৃত্তি ঠিক তত দ্রুত হওয়া উচিত। অন্যদিকে, এগুলি কিছুটা অপ্টিমাইজেশান, আপনি যে কোডটি সহজ এবং আরও পঠনযোগ্য বলে মনে করেন তা চয়ন করুন।

আমার আরও উল্লেখ করা উচিত যে দ্রুততম জিসিডি অ্যালগরিদম ইউক্লিডের অ্যালগরিদম নয়, লেহারের অ্যালগরিদমটি কিছুটা দ্রুত।


আপনি কি এটি বলতে না যেমন পর্যন্ত আমি জানি ? আপনার অর্থ কী ভাষা স্পেসিফিকেশন এই অপ্টিমাইজেশনকে আদেশ দেয় না (এটি যদি হত তবে অবাক হবে), বা বেশিরভাগ বাস্তবায়ন এটি প্রয়োগ করে না?
পিজেট্রাইল 21

1

প্রথমত, টাইট লুপটি প্রতিস্থাপন করতে পুনরাবৃত্তিটি ব্যবহার করবেন না। ইহা ধীরগতি. এটি অপ্টিমাইজ করতে সংকলকটির উপর নির্ভর করবেন না। দ্বিতীয়ত, আপনার কোডে, আপনি প্রত্যেক পুনরাবৃত্ত কলগুলির মধ্যে ম্যাথ.এবস () কল করেন যা অকেজো।

আপনার লুপে, আপনি সহজেই অস্থায়ী ভেরিয়েবলগুলি এড়াতে পারবেন এবং সর্বদা একটি এবং বি অদলবদল করতে পারেন।

int gcd(int a, int b){
    if( a<0 ) a = -a;
    if( b<0 ) b = -b;
    while( b!=0 ){
        a %= b;
        if( a==0 ) return b;
        b %= a;
    }
    return a;
}

A b = b ^ = a ^ = b ব্যবহার করে অদলবদল উত্সকে ছোট করে তোলে তবে সম্পাদন করতে অনেক নির্দেশনা নেয়। এটি অস্থায়ী পরিবর্তনশীল সহ বোরিং অদলবদলের চেয়ে ধীর হবে।


3
“পুনরাবৃত্তি এড়িয়ে চলুন। এটি ধীর ”- সাধারণ পরামর্শ হিসাবে উপস্থাপন করা, এটি জাল। এটি সংকলক উপর নির্ভর করে। সাধারণত, এমন সংকলকগুলির সাথেও যা পুনরাবৃত্তি অপ্টিমাইজ করে না, এটি ধীর নয়, কেবল স্ট্যাক-গ্রাহক।
গিলস

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

-2

জন্য ছোট সংখ্যার ,% বেশ একটি ব্যয়বহুল অপারেশন, সম্ভবত সহজ রিকার্সিভ হয়

GCD[a,b] := Which[ 
   a==b , Return[a],
   b > a, Return[ GCD[a, b-a]],
   a > b, Return[ GCD[b, a-b]]
];

দ্রুত? (দুঃখিত, গাণিতিক কোড এবং সি ++ নয়)


এটা ঠিক দেখাচ্ছে না। খ == 1 এর জন্য, এটি 1 ফিরে আসতে হবে এবং জিসিডি [2,1000000000] ধীর হবে।
ফ্লোরিয়ান এফ

আহ, হ্যাঁ, আমি ভুল করে ফেলেছি। স্থির (আমি মনে করি), এবং স্পষ্ট।
আলেকজান্ডারসন

সাধারণত, জিসিডি [a, 0] এও ফিরে আসা উচিত। তোমার চিরকালের জন্য লুপস।
ফ্লোরিয়ান এফ

আপনার উত্তরে কেবল কোড রয়েছে বলে আমি নীচু হয়েছি। আমরা এই সাইটে ধারণাগুলিতে ফোকাস করতে চাই। উদাহরণস্বরূপ, কেন% ব্যয়বহুল অপারেশন? আমার মতে কোনও অংশের কোডের উপর অনুমান করা এই সাইটের পক্ষে ভাল উত্তর নয়।
জুহো

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

-2

ইউসিলিড অ্যালগরিদম জিসিডি গণনার জন্য সবচেয়ে দক্ষ:

স্ট্যাটিক লম্বা জিসিডি (দীর্ঘ ক, দীর্ঘ খ)
{
যদি (== খ 0)
ফিরে a;
আর
রিটার্ন জিসিডি (, একটি% বি);
}

উদাহরণ: -

যাক এ = 16, বি = 10।
জিসিডি (16, 10) = জিসিডি (10, 16% 10) = জিসিডি (10, 6)
জিসিডি (10, 6) = জিসিডি (6, 10% 6) = জিসিডি (6, 4)
জিসিডি (6, 4) = জিসিডি (4, 6% 4) = জিসিডি (4, 2)
জিসিডি (4, 2) = জিসিডি (2, 4% 2) = জিসিডি (2, 0)


B = 0 যেহেতু GCD (2, 0) 2 আসবে। 

4
এটি প্রশ্নের উত্তর দেয় না। প্রশ্নকর্তা ইউক্লিডের দুটি সংস্করণ উপস্থাপন করেন এবং কোনটি দ্রুত তা জিজ্ঞাসা করেন। আপনি এটি লক্ষ্য করেছেন বলে মনে হয় না এবং কেবল পুনরাবৃত্ত সংস্করণটিকে একমাত্র ইউক্যালিডের অ্যালগরিদম হিসাবে ঘোষণা করে এবং অন্য কোনও কিছুর চেয়ে দ্রুত যে কোনও প্রমাণ দিয়ে জোর দেয় না।
ডেভিড রিচার্বি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.