要完成@Marc Dechico 解决方案,而不是eval,现在更可取的是传递引用(bash >= 4.3):
factorial_bruno() {
local -i val="$1"
local -n var="$2" # $2 reference
_fact() {
if (( $1 <= 1 )); then
var="$val"
return
fi
((val*=$1-1))
_fact $(($1-1))
}
_fact "$1"
}
declare -i res
factorial_bruno 20 res
printf "res=%d\n" "$res"
如果我们比较 @kojiro、@techno 的 1000 次运行的时间(为它们捕获结果,毕竟我们想要结果),@Marc Dechici' s,以及我的解决方案,我们得到:
declare -i res
TIMEFORMAT=$'\t%R elapsed, %U user, %S sys'
echo "Kojiro (not catching result) :"
time for i in {1..1000}; do factorial_kojiro $((i%21)); done >/dev/null
echo "Kojiro (catching result) :"
time for i in {1..1000}; do res=$(factorial_kojiro $((i%21))); done
echo "Techno (not catching result) :"
time for i in {1..1000}; do factorial_techno $((i%21)); done >/dev/null
echo "Techno (catching result, 100% data already cached) :"
time for i in {1..1000}; do res=$(factorial_techno $((i%21))); done
_factorials=(1 1)
echo "Techno (catching result, after cache reset) :"
time for i in {1..1000}; do res=$(factorial_techno $((i%21))); done
echo "Marc Dechico :"
time for i in {1..1000}; do factorial_marc $((i%21)) res; done
echo "This solution :"
time for i in {1..1000}; do factorial_bruno $((i%21)) res; done
Kojiro (not catching result) :
0.182 elapsed, 0.182 user, 0.000 sys
Kojiro (catching result) :
1.510 elapsed, 0.973 user, 0.635 sys
Techno (not catching result) :
0.054 elapsed, 0.049 user, 0.004 sys
Techno (catching result, 100% data already cached) :
0.838 elapsed, 0.573 user, 0.330 sys
Techno (catching result, after cache reset) :
2.421 elapsed, 1.658 user, 0.870 sys
Marc Dechico :
0.349 elapsed, 0.348 user, 0.000 sys
This solution :
0.161 elapsed, 0.161 user, 0.000 sys
有趣的是,在函数中输出 (echo/printf) 并使用 res=$(func...) (subshell) 捕获结果总是非常昂贵,80% 的时间用于 Kojiro 的解决方案,>95% 用于 Techno一个……
编辑:通过添加具有类似解决方案的缓存(@techno 新解决方案 - 不同之处在于使用 printf -v 而不是使用变量引用),如果我们需要计算多次阶乘,我们可以进一步提高响应时间。使用 bash 中的整数限制,这意味着我们需要计算多次相同的阶乘(可能对像这样的基准测试有用:-)