我在Mac上创建了一个名为Armstrong.sh
的bash脚本。
这是一个检查数字是非常强的数字的函数。
# This function works properly
armstrong() {
num=$1 # Making a copy of the received number.
sum=0 # This will store the sum of cubes of each digit from $num
while [ $num -gt 0]; # This loop runs while $num is greater than 0
do
temp=`expr $num % 10` # Extract the last digit of the number
sum=`expr $sum + $temp \* $temp \* $temp` # Cube the last digit and add it to $sum
num=`expr $num / 10` # Remove the last digit of the number
done
if [ $sum -eq $1 ]; # If $sum == $1, i.e., If the number is armstrong
then
echo "$1 is an armstrong number" # print the number
else
echo "$1 is not an armstrong number"
fi
}
当我编写以下代码时,
armstrong 1 # this is an armstrong number
armstrong 153 # This is an armstrong number
armstrong 24 # This is not an armstrong number
然后它的输出如下,
1 is an armstrong number
153 is an armstrong number
24 is not an armstrong number
直到现在,这还不错。
但问题就在这里 当我尝试使用这样的循环打印范围内的所有阿姆斯特朗数字时:
# Accept start and end point of the range
echo -n "Enter start = "
read start
echo -n "Enter end = "
read end
# Loop from start to end point and call the armstrong() function
for ((num = $start; num <= $end; num++))
do
armstrong $num # Calling the function.
done
所以我的问题是:
1&gt; 如何让循环按预期运行?
2&gt; 我是否可以在$temp
函数中使用armstrong()
来编写代码?
就像Java中的sum += Math.pow(num%10, 3);
一样
3&gt; 请给我一个更简洁的方式来编写armstrong
函数。
答案 0 :(得分:5)
您的函数使用变量num
而不将其声明为本地变量,因此它正在更改循环引用的相同shell全局变量,从而重置循环的状态并阻止其完成。
在函数内部,更改
num=$1
到
local num=$1
...并且理想情况下,对函数内的所有其他变量执行相同的操作,除非您明确希望函数修改全局范围内的变量。
答案 1 :(得分:1)
该功能仅检查3位长的阿姆斯特朗号。
阿姆斯特朗数字,也称为Narcissistic Numbers,是数字,它是每个数字加到数字长度幂的总和。
正如@CharlesDuffy所指出的,为避免意外行为,函数内的变量应定义为local
变量。当然,除非他们需要全球访问。
此外,当使用bash
的有限整数表达式时,较大的数字会破坏任何test
或计算数字。
要解决此问题,您可以使用pattern matching进行测试,使用bc
进行计算:
armstrong() {
# Initialize all local variables
local num=$1 sum=0 num_digits=${#1}
# Make sure number is greater than 0
while [[ $num == [1-9]* ]]
do
# Raise the last digit to the length of $num and add it to $sum
sum=$(echo "$sum + (($num % 10)^$num_digits)" | bc)
# Remove the last digit of the number
num=$(echo "scale=0; $num / 10" | bc)
done
if [[ $sum == $1 ]]
then
echo "$1 is an armstrong number"
else
echo "$1 is not an armstrong number"
fi
}
或者,您可以使用parameter expansion迭代num
变量中的每个数字:
for ((i=0;i<=$((num_digits-1));i++)); do
sum=$(echo "$sum + (${num:$i:1}^$num_digits)" | bc)
done