从这个问题Java:获得最大公约数
在获取任何数据类型的gcd时,无论是int
,long
,整数
,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); }
标志:
我注意到的一个区别(除了性能)是标志处理不同,你的手实现了欧几里得算法GCD
和我的gcdLongIterative
表现相同,但两者都不同于大整数
,后者倾向于“保持”标志因为他们是。似乎本质上,GCD
和gcdLongIterative
可以返回负数,而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();
}
}
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)