《编程之美》学而思 - 最大公约数问题

《编程之美》学而思 - 最大公约数问题

flyfish

greatest common divisor 最大公约数
Euclidean algorithm, or Euclid’s algorithm 欧几里德算法
common divisor 公约数
divisor 除数; 因子;

主要方法
列举法:各自列出约数,再找出最大的公约数。
质因数分解法:两数各作素因数分解,然后取出共有的项乘起来。
短除法
辗转相除法(欧几里德算法)
辗转相除法首次出现于欧几里得的《几何原本》

质因数(素因数或质因子)在数论里是指能整除给定正整数的质数。除了1以外,两个没有其他共同质因子的正整数称为互质。因为1没有质因子,1与任何正整数(包括1本身)都是互质。正整数的因数分解可将正整数表示为一连串的质因子相乘

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

/* Standard C Function: Greatest Common Divisor */
int gcd ( int a, int b )
{
  int c;
  while ( a != 0 ) {
     c = a; a = b%a;  b = c;
  }
  return b;
}

/* Recursive Standard C Function: Greatest Common Divisor */
int 
gcdr ( int a, int b )
{
  if ( a==0 ) return b;
  return gcdr ( b%a, a );
}

标准库 std::gcd(C++17)
VS 2017.3 [P2] C++17 P0295R0 gcd(), lcm()

Libstdc++ 中的算法
欧几里得整环(Euclidean domain)是一种能作辗转相除法的整环
Euclidean domain 和 Euclidean ring是一个意思

template<typename _EuclideanRingElement>
    _EuclideanRingElement
    __gcd(_EuclideanRingElement __m, _EuclideanRingElement __n)
    {
      while (__n != 0)
    {
      _EuclideanRingElement __t = __m % __n;
      __m = __n;
      __n = __t;
    }
      return __m;
    }

Boost库中的算法

#include 

common_factor_rt.hpp

boost::math::gcd


    gcd_euclidean
    (
        RingType a,
        RingType b
    )
    {
        // Avoid repeated construction
        #ifndef __BORLANDC__
        RingType const  zero = static_cast( 0 );
        #else
        RingType  zero = static_cast( 0 );
        #endif

        // Reduce by GCD-remainder property [GCD(a,b) == GCD(b,a MOD b)]
        while ( true )
        {
            if ( a == zero )
                return b;
            b %= a;

            if ( b == zero )
                return a;
            a %= b;
        }
    }

二进制最大公约数算法将除法操作替换成了二进制的移位

 // Greatest common divisor for unsigned binary integers
    template < typename BuiltInUnsigned >
    BuiltInUnsigned
    gcd_binary
    (
        BuiltInUnsigned  u,
        BuiltInUnsigned  v
    )
    {
        if ( u && v )
        {
            // Shift out common factors of 2
            unsigned  shifts = 0;

            while ( !(u & 1u) && !(v & 1u) )
            {
                ++shifts;
                u >>= 1;
                v >>= 1;
            }

            // Start with the still-even one, if any
            BuiltInUnsigned  r[] = { u, v };
            unsigned         which = static_cast<bool>( u & 1u );

            // Whittle down the values via their differences
            do
            {
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
                while ( !(r[ which ] & 1u) )
                {
                    r[ which ] = (r[which] >> 1);
                }
#else
                // Remove factors of two from the even one
                while ( !(r[ which ] & 1u) )
                {
                    r[ which ] >>= 1;
                }
#endif

                // Replace the larger of the two with their difference
                if ( r[!which] > r[which] )
                {
                    which ^= 1u;
                }

                r[ which ] -= r[ !which ];
            }
            while ( r[which] );

            // Shift-in the common factor of 2 to the residues' GCD
            return r[ !which ] << shifts;
        }
        else
        {
            // At least one input is zero, return the other
            // (adding since zero is the additive identity)
            // or zero if both are zero.
            return u + v;
        }
    }

你可能感兴趣的:(有趣的问题,基础算法)