2010-08-03 3 views
3
fact() 
{ 
    if [ $1 -eq 1 ] 
    then 
     return 1 
    else 
     y=`expr $1 - 1` 
     fact $y 
     b=$(($1 * $?)) 
     return $b 
    fi 
} 
echo "enter" 
read n 
fact $n 
echo "$?" 

Это программа для поиска факториала числа. Результат корректный до 5. Вывод 6 дает значение 208, но правильный ответ 720. Что вызывает эту ошибку?Почему моя функция bash возвращает неправильное значение?

+0

возможно дубликат из [Как найти факториал числа в сценарии Bash?] (http://stackoverflow.com/questions/3394580/how-do-you-find-the-factorial-of-a-number-in- a-bash-script) –

ответ

7

Функция возвращает значения могут идти только до 255:

a() 
{ 
     return 255 
} 

a 
echo $? 

b() 
{ 
     return 256 
} 

b 
echo $? 

Производит:

$ bash x.sh 
255 
0 

return, как exitexit и может принимать значения только до 255 (http://www.unix.org/whitepapers/shdiffs.html).

Один из вариантов заключается в том, чтобы переключиться на итеративное предложение, как описано в другом ответе. В качестве альтернативы вы можете использовать эхо и захватить Рекурсивный вывод, который так:

#!/bin/bash 

fact() 
{ 
    if [ $1 -eq 1 ] 
    then 
     echo 1 
    else 
     y=$(expr $1 - 1) 
     f=$(fact $y) 
     b=$(($1 * $f)) 
     echo $b 
    fi 
} 
echo "enter" 
read n 
fact $n 
1

Интересно, что программа работает, как ожидалось, используя тире, он не только с помощью Баш. Таким образом, похоже, что это багизм.

Просто добавьте строку

#!/bin/dash 

в верхней части программы, и это работает!

+0

+1 для любопытства. Я бы ожидал, что он снова сломается за несколько большее количество. – tripleee

2

Bourne shell can not store много в $? (код выхода). предел 255. Heres альтернативный способ

n=0 
on=0 
fact=1 

echo -n "Enter number to find factorial : " 
read n 

on=$n 

while [ $n -ge 1 ] 
do 
    fact=`expr $fact \* $n` 
    n=`expr $n - 1` 
done 

echo "Factorial for $on is $fact" 
1

Bash скрипты и функции Bash возвращаемые значения предназначены для быть возвращены коды, и, таким образом ограничен со значениями они способны возвращаться. Вы не должны зависеть от значений grater, а затем 127 (как правило, значения, которые являются более термальными, а затем 127 - до 255 - используются для обозначения полученных сигналов).

Линии

fact $y 
b=$(($1 * $?)) 

ожидают использовать код возврата $? из fact, и этот код не может быть терке затем 255.

Баш способ возврата значений печатает их, и синтаксический анализ или оценивая этот результат.

2

Что вы видите, это количество возвращаемых значений функции при 256. 720 mod 256 is 208 (256 + 256 + 208 = 720).

Мой совет, если вы должны использовать функцию оболочки, это сделать:

#!/bin/bash 
fact() 
{ 
    if [ "$1" -eq "1" ] 
    then 
     echo 1 
     return 
    fi 
    y=`expr $1 - 1` 
    z=$(fact $y) 
    echo $(($1 * $z)) 
} 
echo "enter" 
read n 
echo "$(fact $n)" 

Это использует стандартный вывод для возврата значений, а не код возврата.

Или, еще лучше, использовать правильные инструменты для работы:

pax> echo 'define f(x) {if (x>1){return x*f(x-1)};return 1} 
      f(6)' | bc 
720 
pax> echo 'define f(x) {if (x>1){return x*f(x-1)};return 1} 
      f(500)' | BC_LINE_LENGTH=99999 bc 
12201368259911100687
45373153881997605496447502203281863013616477148203584163378722078177 
20048078520515932928547790757193933060377296085908627042917454788242 
49127263443056701732707694610628023104526442188787894657547771498634 
94367781037644274033827365397471386477878495438489595537537990423241 
06127132698432774571554630997720278101456108118837370953101635632443 
29870295638966289116589747695720879269288712817800702651745077684107 
19624390394322536422605234945850129918571501248706961568141625359056 
69342381300885624924689156412677565448188650659384795177536089400574 
52389403357984763639449053130623237490664450488246650759467358620746 
37925184200459369692981022263971952597190945217823331756934581508552 
33282076282002340262690789834245171200620771464097945611612762914595 
12372299133401695523638509428855920187274337951730145863575708283557 
80158735432768888680120399882384702151467605445407663535984174430480 
12893831389688163948746965881750450692636533817505547812864000000000 
00000000000000000000000000000000000000000000000000000000000000000000 
00000000000000000000000000000000000000000000000 

Я хотел бы видеть bash -только решение вычислить факториал 500 :-)

Смежные вопросы