我编写了一个使用递归来查找最大公因数(分母)的函数:
> gcd
function(a,b){
if (length(a)*length(b)>1) {
warning("Only scalars allowed; using first elements.")
a<-a[1]
b<-b[1]
}
ifelse (b==0, a, gcd(b, a %% b))
}
然后我跑了一些microbenchmark
测试针对pracma::gcd
,它使用重复的除法例程。以下是一些极端情况的结果:
Rgames>microbenchmark(pracma::gcd(2^2*3*5^2*7*11^8*23^5*41^2,2^1*3^8*5^2*7*11^3*23^5*47^2),gcd(2^2*3*5^2*7*11^8*23^5*41^2,2^1*3^8*5^2*7*11^3*23^5*47^2),times=10)
Unit: microseconds
expr
pracma::gcd(2^2 * 3 * 5^2 * 7 * 11^8 * 23^5 * 41^2, 2^1 * 3^8 * 5^2 * 7 * 11^3 * 23^5 * 47^2)
gcd(2^2 * 3 * 5^2 * 7 * 11^8 * 23^5 * 41^2, 2^1 * 3^8 * 5^2 * 7 * 11^3 * 23^5 * 47^2)
min lq median uq max neval
140.260 142.399 158.0070 184.733 285.225 10
237.759 241.607 250.3725 255.291 282.231 10
Rgames> microbenchmark(pracma::gcd(2^16,2^16*3),gcd(2^16,2^16*3),times=10)
Unit: microseconds
expr min lq median uq max neval
pracma::gcd(2^16, 2^16 * 3) 58.585 59.867 61.5780 67.992 140.688 10
gcd(2^16, 2^16 * 3) 25.658 26.941 28.8655 30.790 41.052 10
我不完全确定,但似乎pracma
当涉及大素数时,代码会更快,而当涉及大素数时,我的玩具代码会更快。素数的力量似乎并不是主要驱动力。
关于什么在控制这里的相对时间有什么想法吗?
这是pracma
code:
function (a, b, extended = FALSE)
{
stopifnot(is.numeric(a), is.numeric(b))
if (length(a) == 1) {
a <- rep(a, times = length(b))
}
else if (length(b) == 1) {
b <- rep(b, times = length(a))
}
n <- length(a)
e <- d <- g <- numeric(n)
for (k in 1:n) {
u <- c(1, 0, abs(a[k]))
v <- c(0, 1, abs(b[k]))
while (v[3] != 0) {
q <- floor(u[3]/v[3])
t <- u - v * q
u <- v
v <- t
}
e[k] <- u[1] * sign(a[k])
d[k] <- u[2] * sign(a[k])
g[k] <- u[3]
}
if (extended) {
return(list(g = g, c = e, d = d))
}
else {
return(g)
}
}
编辑:额外问题:如果我们可以识别导致差异的数据类型,我们可以提前预测哪个函数将解决问题gcd(x,y)
不分析x
and y
的可分解性?