求最大公约数

1、辗转相除法,因为(x,y)的公约数可以通过下面的分析求得,x可以表示为ky + b,那么(x,y)的公约数可以表示为(ky+b,y)的公约数,也就变成(b,y)的公约数,而b=x % y,且b <=y,这样可以递归调用(y,b)(b,y%b) ...直到y%b ==0为止。

2、既然ky+b 与y有相同的最大公约数,那么如果x>y,(x-y,y)和(x,y)的最大公约数也是相同的,这样不断递归下去直到x==y,可以求得最大公约数代码如下:

#include <stdio.h>
int GreatestCommonDivisor(int value1, int value2) {
  int tmp  = value1 % value2;
  if (tmp  == 0) {
    return value2;
  } else {
    return GreatestCommonDivisor(value2, tmp);
  }
}
int GreatestCommonDivisor1(int value1, int value2) {
  if (value1 > value2) {
    return GreatestCommonDivisor(value1 - value2, value2);
  } else if(value1 == value2) {
    return value1;
  } else {
    return GreatestCommonDivisor(value1, value2 - value1);
  }
}
int main(int argc, char** argv) {
  int value1 = 4;
  int value2 = 7;  
  printf("the greatest common divisor of %d and %d is %d\n", value1, value2, GreatestCommonDivisor(value1, value2));
  printf("the greatest common divisor of %d and %d is %d\n", value1, value2, GreatestCommonDivisor1(value1, value2));
}

3、前两种方法,都有一些缺点,辗转相除方法虽然递归的次数比较少,但计算模的代价比较大,而相减法虽然计算代价相对小,但有些情况下递归的次数非常大,因此方法3将两种策略结合起来,分一下几种情况处理:

1)如果x,y都是偶数,那么一定有一个公因子2,然后将x,y都除以二,即左移1位,再递归求公因子

2)如果x,y一个奇数,一个偶数,那么偶数除以2(左移1位)后,再递归求公因子是一样的

3)如果x,y都是奇数,使用相减法递归求公因子

具体代码如下:

#include <stdio.h>
int GreatestCommonDivisor(int value1, int value2) {
  int tmp  = value1 % value2;
  if (tmp  == 0) {
    return value2;
  } else {
    return GreatestCommonDivisor(value2, tmp);
  }
}
int GreatestCommonDivisor1(int value1, int value2) {
  if (value1 > value2) {
    return GreatestCommonDivisor(value1 - value2, value2);
  } else if(value1 == value2) {
    return value1;
  } else {
    return GreatestCommonDivisor(value1, value2 - value1);
  }
}
bool IsEven(int value) {
  return (value & 0x01) != 1;
}
int GreatestCommonDivisor2(int value1, int value2) {
  int greatest_common_divisor = 1;
  if (IsEven(value1) && IsEven(value2)) {
    if (value1 >0 && value2 >0) {
      greatest_common_divisor *=2;
      greatest_common_divisor *= GreatestCommonDivisor2(value1>>1, value2>>1);
    } else {
      return 1;
    }
  } else if (IsEven(value1)) {
    if (value1 > 0) {
      greatest_common_divisor *= GreatestCommonDivisor2(value1>>1, value2);
    } else {
      return 1;
    }
  } else if(IsEven(value2)) {
    if (value2 >0) {
      greatest_common_divisor *= GreatestCommonDivisor2(value1, value2>>1);
    } else {
      return 1;
    }
  } else {
    if (value1 > value2) {
      greatest_common_divisor *= GreatestCommonDivisor2(value1 - value2, value2);
    } else if (value1 < value2) {
      greatest_common_divisor *= GreatestCommonDivisor2(value1, value2 - value1);
    } else {
      greatest_common_divisor *= value1;
    }
  }
  return greatest_common_divisor;
}
                                 
int main(int argc, char** argv) {
  int value1 = 13;
  int value2 = 65;  
  printf("the greatest common divisor of %d and %d is %d\n", value1, value2, GreatestCommonDivisor(value1, value2));
  printf("the greatest common divisor of %d and %d is %d\n", value1, value2, GreatestCommonDivisor1(value1, value2));
  printf("the greatest common divisor of %d and %d is %d\n", value1, value2, GreatestCommonDivisor2(value1, value2));
}

参考文献:

编程之美2.7

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值