c++ sans cmath 库中的 GCD 函数

GCD function in c++ sans cmath library

本文关键字:GCD 函数 sans cmath c++      更新时间:2023-10-16

我正在写一个混合数字类,需要一个快速简便的"最大公约数"函数。任何人都可以给我代码或代码链接吗?

libstdc++ 算法库有一个隐藏的 gcd 函数(我使用的是 g++ 4.6.3)。

#include <iostream>
#include <algorithm>
int main()
{
  std::cout << std::__gcd(100,24); // print 4
  return 0;
}

欢迎您:)

更新:正如@chema989所指出的,在 C++17 中,<numeric>标题std::gcd()可用的功能。

我很

想投票关闭 - 似乎很难相信很难找到实现,但谁能确定。

template <typename Number>
Number GCD(Number u, Number v) {
    while (v != 0) {
        Number r = u % v;
        u = v;
        v = r;
    }
    return u;
}

在 C++ 17 或更高版本中,您可以#include <numeric> 并使用std::gcd(如果您关心 gcd,那么您很有可能也会对添加的std::lcm感兴趣)。

一个快速递归版本:

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 类)。

这个函数实际上来自我早期的答案,用于计算屏幕尺寸的积分纵横比,但原始来源是我很久以前学到的欧几里得算法,如果你想知道它背后的数学,在维基百科上有详细说明。


a)一些递归解决方案的问题在于,它们接近答案的速度太慢,以至于在到达那里之前往往会耗尽堆栈空间,例如考虑非常糟糕的(伪代码):

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

你会发现这在像sum (1, 1000000000)这样的东西上非常昂贵,因为你(试图)用完了十亿左右的堆栈帧。递归的理想用例类似于二叉搜索,每次迭代的解决方案空间减少一半。最大的公约数也是解决方案空间迅速减少的公约数,因此对大量堆栈使用的担忧是没有根据的。

对于 C++17,您可以使用标头 <numeric> 中定义的std::gcd

auto res = std::gcd(10, 20);

欧几里得算法很容易用 C 语言编写。

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