当前位置: 首页 > 知识库问答 >
问题:

Java:求最大公约数,哪种方法更好?

于高雅
2023-03-14

从这个问题Java:获得最大公约数

在获取任何数据类型的gcd时,无论是intlong整数Long,哪个答案在精度,速度,cpu使用等方面更好?

A:

private static int gcdThing(int a, int b) {
    return BigInteger.valueOf(a).gcd(BigInteger.valueOf((b))).intValue();
}

B:

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

共有2个答案

危彬彬
2023-03-14

标志:

我注意到的一个区别(除了性能)是标志处理不同,你的手实现了欧几里得算法GCD和我的gcdLongIterative表现相同,但两者都不同于大整数,后者倾向于“保持”标志因为他们是。似乎本质上,GCDgcdLongIterative可以返回负数,而Bigintger将只返回正数。

GCD and gcdLongIterative implementations:
 -4/-2   => 2/1
-10/200  => 1/-20
 10/-200 => 1/-20

BigInteger implementation tends to 'keep' the signs:
 -4/-2   => -2/-1
-10/200  => -1/20
 10/-200 => 1/-20

当用于分数时,所有结果都是有效的,但如果您希望数字具有特定的“风格”,则值得考虑后处理标准化。

性能:

如果你想使用<代码> GCD < /代码>,因为那是比较快的,那么你应该考虑它的迭代实现:

  public static long gcdLongIterative(long a, long b) {
    long tmp;
    
    while (0 != b) {
      tmp = b;
      b   = a % b;
      a   = tmp;
    }
    
    return a;
  }  

受@Xabster benchmark的启发,我对其进行了扩展,以测试所有3种实现,在某些情况下,递归和迭代都执行相同的操作,但在大多数情况下,迭代的速度稍快一些:

(100 000 000 iterations)
gcd recursive:  3113ms
gcd iterative:  3079ms
gcd BigInteger: 13672ms

基准代码如下:

import java.math.BigInteger;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

public class Test {
  
  private static final int BENCHMARK_ITERATIONS = 100000000; 
  

  public static long gcdLong(long a, long b) {
    return b == 0 ? a : gcdLong(b, a % b);
  }

  
  public static long gcdLongIterative(long a, long b) {
    long tmp;
    
    while (0 != b) {
      tmp = b;
      b   = a % b;
      a   = tmp;
    }
    
    return a;
  }  
  
  
  public static long gcdLongBigInteger(long a, long b) {
    return BigInteger.valueOf(a).gcd(BigInteger.valueOf((b))).longValue();
  }

  
  public static String asFractionGcdLong(long a, long b) {
    long gcd = gcdLong(a, b);
    return (a / gcd) + "/" + (b / gcd);
  }

  
  public static String asFractionGcdLongIterative(long a, long b) {
    long gcd = gcdLongIterative(a, b);
    return (a / gcd) + "/" + (b / gcd);
  }
  
  
  public static String asFractionGcdLongBI(long a, long b) {
    long gcd = gcdLongBigInteger(a, b);
    return (a / gcd) + "/" + (b / gcd);
  }
  
  
  public static void test(String actual, String expected) {
    boolean match = expected.equals(actual);
    
    if (match) {
      System.out.println("Actual and expected match=" + expected);      
    } else {
      System.out.println("NO match expected=" + expected + " actual=" + actual);            
    }
  }
  
  
  public static class Values {
    public long   a;
    public long   b;
    public String expected;

    public Values(long a, long b, String expected) {
      this.a = a;
      this.b = b;
      this.expected = expected;
    }
  }
  
  
  public static void validityTest() {
    List<Values> vals = new LinkedList<Values>(Arrays.asList(
        new Values(500, 1000, "1/2"),
        new Values(17,  3,    "17/3"),
        new Values(462, 1071, "22/51"),
        new Values(-4,  -2,   "2/1"),
        new Values(-10, 200,  "1/-20"),
        new Values(10,  -200, "1/-20")
    ));
    
    System.out.println("------  Recursive implementation -------");
    vals.forEach(v -> test(asFractionGcdLong(v.a, v.b), v.expected));
    System.out.println();    
    
    System.out.println("------  Iterative implementation -------");    
    vals.forEach(v -> test(asFractionGcdLongIterative(v.a, v.b), v.expected));
    System.out.println();    

    System.out.println("------  BigInteger implementation -------");    
    vals.forEach(v -> test(asFractionGcdLongBI(v.a, v.b), v.expected));
    System.out.println();    
  }

  
  public static void benchMark() {
    Random r = new Random();
    
    long[] nums = new long[BENCHMARK_ITERATIONS];
    for (int i = 0 ; i < nums.length ; i++) nums[i] = r.nextLong();

    System.out.println("Waming up for benchmark...");
    for (int i = 0 ; i < nums.length-1; i++) gcdLong(i, i + 1);
    for (int i = 0 ; i < nums.length-1; i++) gcdLongIterative(i, i + 1);
    for (int i = 0 ; i < nums.length-1; i++) gcdLongBigInteger(i, i + 1);

    System.out.println("Started benchmark...");
    long s = System.currentTimeMillis();
    for (int i = 0 ; i < nums.length-1; i++) gcdLong(i, i + 1);
    System.out.println("recursive:  " + (System.currentTimeMillis() - s) + "ms");

    s = System.currentTimeMillis();
    for (int i = 0 ; i < nums.length-1; i++) gcdLongIterative(i, i + 1);
    System.out.println("iterative:  " + (System.currentTimeMillis() - s) + "ms");    
    
    s = System.currentTimeMillis();
    for (int i = 0 ; i < nums.length-1; i++) gcdLongBigInteger(i, i + 1);
    System.out.println("BigInteger: " + (System.currentTimeMillis() - s) + "ms");    
  }
  
  
  public static void main(String[] args) {
    validityTest();
    benchMark();
  }
  
}
骆照
2023-03-14
    Random r = new Random();
    int[] ints = new int[500000];
    for (int i = 0 ; i < ints.length ; i++)
        ints[i] = r.nextInt();

    for (int i = 0 ; i < ints.length-1; i++)
        GCD(i,i+1);
    for (int i = 0 ; i < ints.length-1; i++)
        gcdThing(i, i + 1);

    long start = System.currentTimeMillis();
    for (int i = 0 ; i < ints.length-1; i++)
        GCD(i,i+1);
    System.out.println("GCD: " + (System.currentTimeMillis() - start));

    start = System.currentTimeMillis();
    for (int i = 0 ; i < ints.length-1; i++)
        gcdThing(i, i + 1);
    System.out.println("gcdThing: " + (System.currentTimeMillis() - start));

打印:

GCD: 13

gcdThing: 124

 类似资料:
  • 本文向大家介绍java求最大公约数与最小公倍数的方法示例,包括了java求最大公约数与最小公倍数的方法示例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了java求最大公约数与最小公倍数的方法。分享给大家供大家参考,具体如下: Gongyueshu.java文件: 此处需要由控制台输入参数,eclipse环境运行的设置步骤为Run》Run Configurations进入运行的调试配置界面

  • 本文向大家介绍PHP编程求最大公约数与最小公倍数的方法示例,包括了PHP编程求最大公约数与最小公倍数的方法示例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了PHP编程求最大公约数与最小公倍数的方法。分享给大家供大家参考,具体如下: PS:这里再为大家推荐几款在线计算工具供大家参考使用: 在线一元函数(方程)求解计算工具: http://tools.jb51.net/jisuanqi/eq

  • 问题内容: 我已经看到存在这样的功能,即。是否有在Java中的其它功能也适用于其他类型的工作(,或)?似乎这是有意义的(带有各种重载),但是它不存在。在别的地方吗? (请不要将此问题与“我如何自己实现”混淆!) 问题答案: 对于int和long而言,作为原语,并非如此。对于Integer,有人可能写了一个。 假设BigInteger是int,Integer,long和Long的(数学/函数)超集,

  • Python3 实例 以下代码用于实现最大公约数算法: 实例(Python 3.0+)# Filename : test.py # author by : www.runoob.com # 定义一个函数 def hcf(x, y): """该函数返回两个数的最大公约数""" # 获取最小值 if x > y: smaller = y else: smaller = x for i in range

  • 我试图让这个程序计算两个用户输入的正整数(x和y)的最大公约数(GCD)。set函数不返回可以索引的列表。关于如何找到GCD有什么建议吗?

  • 计算两个或两个以上数字/数字数组的最大公约数。 内部的 _gcd 函数使用递归。基本情况是,当 y 等于 0 的情况下,返回 x 。否则,返回 y 的最大公约数和x / y的其余数。 const gcd = (...arr) => { const _gcd = (x, y) => (!y ? x : gcd(y, x % y)); return [...arr].reduce((a, b)