最大公约数

  1. /// Greatest Common Divisor.
  2. ///
  3. /// greatest_common_divisor(num1, num2) returns the greatest number of num1 and num2.
  4. ///
  5. /// Wikipedia reference: https://en.wikipedia.org/wiki/Greatest_common_divisor
  6. /// gcd(a, b) = gcd(a, -b) = gcd(-a, b) = gcd(-a, -b) by definition of divisibility
  7. pub fn greatest_common_divisor_recursive(a: i64, b: i64) -> i64 {
  8. if a == 0 {
  9. b.abs()
  10. } else {
  11. greatest_common_divisor_recursive(b % a, a)
  12. }
  13. }
  14. pub fn greatest_common_divisor_iterative(mut a: i64, mut b: i64) -> i64 {
  15. while a != 0 {
  16. let remainder = b % a;
  17. b = a;
  18. a = remainder;
  19. }
  20. b.abs()
  21. }
  22. #[cfg(test)]
  23. mod tests {
  24. use super::*;
  25. #[test]
  26. fn positive_number_recursive() {
  27. assert_eq!(greatest_common_divisor_recursive(4, 16), 4);
  28. assert_eq!(greatest_common_divisor_recursive(16, 4), 4);
  29. assert_eq!(greatest_common_divisor_recursive(3, 5), 1);
  30. assert_eq!(greatest_common_divisor_recursive(40, 40), 40);
  31. assert_eq!(greatest_common_divisor_recursive(27, 12), 3);
  32. }
  33. #[test]
  34. fn positive_number_iterative() {
  35. assert_eq!(greatest_common_divisor_iterative(4, 16), 4);
  36. assert_eq!(greatest_common_divisor_iterative(16, 4), 4);
  37. assert_eq!(greatest_common_divisor_iterative(3, 5), 1);
  38. assert_eq!(greatest_common_divisor_iterative(40, 40), 40);
  39. assert_eq!(greatest_common_divisor_iterative(27, 12), 3);
  40. }
  41. #[test]
  42. fn negative_number_recursive() {
  43. assert_eq!(greatest_common_divisor_recursive(-32, -8), 8);
  44. assert_eq!(greatest_common_divisor_recursive(-8, -32), 8);
  45. assert_eq!(greatest_common_divisor_recursive(-3, -5), 1);
  46. assert_eq!(greatest_common_divisor_recursive(-40, -40), 40);
  47. assert_eq!(greatest_common_divisor_recursive(-12, -27), 3);
  48. }
  49. #[test]
  50. fn negative_number_iterative() {
  51. assert_eq!(greatest_common_divisor_iterative(-32, -8), 8);
  52. assert_eq!(greatest_common_divisor_iterative(-8, -32), 8);
  53. assert_eq!(greatest_common_divisor_iterative(-3, -5), 1);
  54. assert_eq!(greatest_common_divisor_iterative(-40, -40), 40);
  55. assert_eq!(greatest_common_divisor_iterative(-12, -27), 3);
  56. }
  57. #[test]
  58. fn mix_recursive() {
  59. assert_eq!(greatest_common_divisor_recursive(0, -5), 5);
  60. assert_eq!(greatest_common_divisor_recursive(-5, 0), 5);
  61. assert_eq!(greatest_common_divisor_recursive(-64, 32), 32);
  62. assert_eq!(greatest_common_divisor_recursive(-32, 64), 32);
  63. assert_eq!(greatest_common_divisor_recursive(-40, 40), 40);
  64. assert_eq!(greatest_common_divisor_recursive(12, -27), 3);
  65. }
  66. #[test]
  67. fn mix_iterative() {
  68. assert_eq!(greatest_common_divisor_iterative(0, -5), 5);
  69. assert_eq!(greatest_common_divisor_iterative(-5, 0), 5);
  70. assert_eq!(greatest_common_divisor_iterative(-64, 32), 32);
  71. assert_eq!(greatest_common_divisor_iterative(-32, 64), 32);
  72. assert_eq!(greatest_common_divisor_iterative(-40, 40), 40);
  73. assert_eq!(greatest_common_divisor_iterative(12, -27), 3);
  74. }
  75. }