2012-06-08 4 views
19

私は混合数値クラスを作成していて、すばやく簡単な「最大公約数」関数が必要です。誰か私にコードやコードへのリンクを教えてもらえますか?C++でのGCD関数sans cmathライブラリ

+0

:それは '最大公約数' と呼ばれます。 – bjoernz

+0

楽しいものがたくさんあります:http://codegolf.stackexchange.com/questions/35587/ – technosaurus

答えて

30

私は投票に賛成できません。実装を見つけるのは難しいと信じるのは難しいようですが、確かに分かっています。

unsigned GCD(unsigned u, unsigned v) { 
    while (v != 0) { 
     unsigned r = u % v; 
     u = v; 
     v = r; 
    } 
    return u; 
} 
+1

ありがとうございました。そして、私は20分間グーグルでグーグル・グーグルでプレーし、明確な結果を得られなかった。 –

+0

なぜ符号なしを使用するのですか? –

+0

@EnjoysMath:ほとんどの場合、GCDを使いたいと思っているのは、ほとんどの場合、あなたは符号なしの数字を扱っているからです。 –

16

迅速な再帰バージョン:

unsigned int gcd (unsigned int n1, unsigned int n2) { 
    return (n2 == 0) ? n1 : gcd (n2, n1 % n2); 
} 

または同等の反復バージョンあなたが激しく再帰に反対している場合(a)の:自分で

unsigned int gcd (unsigned int n1, unsigned int n2) { 
    unsigned int tmp; 
    while (n2 != 0) { 
     tmp = n1; 
     n1 = n2; 
     n2 = tmp % n2; 
    } 
    return n1; 
} 

だけで代用(例えば、bignumクラスのような非基本型を使用している場合)、データ型、ゼロ比較、代入、モジュラスの各メソッドがあります。

この関数は実際には画面サイズの積分アスペクト比を計算するためにearlier answer of mineから来ましたが、元のソースは長い時間前に学んだユークリッドアルゴリズムでした。詳細はhere on Wikipediaです。


(a)は、いくつかの再帰的なソリューションと問題は、あなたがそこに着く前に、彼らはこのように非常に悪い考え抜か(擬似のように、あなたはスタック領域が不足する傾向があるので、ゆっくりと答えに近づくということですコード):あなたは()億を使い切るかそこらのフレームをスタックしようとして

def sum (a:unsigned, b:unsigned): 
    if b == 0: return a 
    return sum (a + 1, b - 1) 

あなたはsum (1, 1000000000)のようなものには、非常に高価な見つけることができます。再帰の理想的なユースケースはバイナリ検索のようなもので、反復ごとにソリューションの領域を半分に減らします。最大公約数は、解空間が急速に縮小され、大量のスタック使用に関する不安がそこに根付いていないものです。

+0

+1 'int'を置き換えるために' template 'を追加し、関数の前に' constexpr'キーワードを追加してコンパイル時/ランタイムジェネリック関数を作成することもできます。 – authchir

+0

2番目の方法で入力ミスが発生する可能性があります。それは 'return n1'でしょうか?その点では、n2は常に定義上常にゼロになる。 –

+0

良いキャッチ、@ジム、それを修正しました。 – paxdiablo

4

EuclideanアルゴリズムはのlibstdC++アルゴリズムライブラリは、(私はG ++ 4.6.3を使用しています)隠しGCD機能を持つC.

int gcd(int a, int b) { 
    while (b != 0) { 
    int t = b; 
    b = a % b; 
    a = t; 
    } 
    return a; 
} 
47

書くことは非常に簡単です。

#include <iostream> 
#include <algorithm> 

int main() 
{ 
    cout << std::__gcd(100,24); 
    return 0; 
} 

あなたは

UPDATE歓迎:)です:@のchema989はC++ 17で、それを指摘したように<numeric>ヘッダーで使用可能なstd::gcd()機能があります。

+18

ライブラリリリース間で変更できるため、文書化されていない機能に頼るべきではありません。 – vmrob

+0

MSVCで利用できますか? –

+1

@vmrob:合意。いつでもSTLから実装をコピーできます。 Mbt925:完了。 –

-2

私の2セント。符号なし整数型のためXOR swapを使用してテンプレートユークリッドアルゴリズム:

template <class Unsigned> 
Unsigned gcd(Unsigned a, Unsigned b) 
{ 

    static_assert(
     std::numeric_limits<Unsigned>::is_integer && 
     !std::numeric_limits<Unsigned>::is_signed, "Unsigned required."); 

    while (b) 
    { 
     b ^= a; 
     a ^= b; 
     b = (b^a) % a; 
    } 
    return a; 
} 
+0

これはなぜdv'dが得られるか知っていればよいでしょう。 – Sheljohn

+2

コンパイラの仕事をしようとしているからです。しないでください。 XORのスワップについて知っています。あなたができることに干渉する可能性が高くなります(ループの展開など)。 – einpoklum

+0

これは餌を浮かべようとすると壊れます。 xor-swapの代わりに通常のスワップを使用した場合、それは起こりません。また、@ einpoklumのように、適用されない他の最適化もあります。 CPUはxorsのために使用されない特別なスワップ命令を持つかもしれません。 – Pharap

5

ヘッダ<numeric>で定義されたstd::gcdあなたが使用できる17 C++の場合:ところで

auto res = std::gcd(10, 20); 
関連する問題