2010-08-03 37 views

Trả lời

7
#!/bin/bash 
counter=$1 #first argument 
factorial=1 
while [ $counter -gt 0 ] #while counter > 0 
do 
    factorial=$(($factorial * $counter)) 
    counter=$(($counter - 1)) 
done 
echo $factorial 
4
echo 500 | dc -e '?[q]sQ[d1=Qd1-lFx*]dsFxp' 
+1

1 tốt đẹp, mặc dù tôi không có đầu mối tại sao nó hoạt động;) –

+0

này sử dụng một chương trình bên ngoài với một cú pháp phức tạp để thực hiện các phép tính. –

+1

@ luther, các công cụ chuyên dụng bên ngoài như bc, dc có thể tính số lớn hơn. Vì vậy, họ là công cụ thích hợp nhất cho công việc. Có giới hạn cho những gì bash có thể tính toán cho giai thừa lớn hơn. – ghostdog74

4

10! trong bash:

f=1; for k in {1..10}; do f=$[$k * $f] ; done; echo $f 

hoặc ở đây trong một từng bước thời trang:

$ t=$(echo {1..10}) 
$ echo $t 
1 2 3 4 5 6 7 8 9 10 
$ t=${t// /*} 
$ echo $t 
1*2*3*4*5*6*7*8*9*10 
$ echo $[$t] 
3628800 
+0

có giới hạn cho những gì bash có thể làm. nó phá vỡ cho số lượng lớn hơn.Có lẽ bạn có một cách để sản xuất các kết quả tương tự cho giai thừa của nói, ví dụ, 500, với bash? – ghostdog74

+0

Tôi ổn với bất kỳ ai sử dụng các công cụ bên ngoài để tính toán những gì họ cần. Nhưng OP hỏi làm thế nào để làm điều này trong bash, vì vậy tôi figured này rất có thể là một tập thể dục trong "bash cho lập trình chung", chương "làm thế nào để lặp trong bash". –

9

Bạn không làm điều đó trong bash. Người thông minh không cố gắng chặt cây bằng cá, vì vậy lời khuyên của tôi là thử và sử dụng đúng công cụ cho công việc.

Bạn có thể sử dụng, ví dụ, bc để làm điều đó như sau:

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 
+3

Đồng ý. OTOH Tôi đã tìm thấy bản thân mình một thời gian trong một khu rừng với một cái búa, một con dao bơ và busybox. Vì vậy, điều này nên được gắn thẻ là "đào tạo sự sống còn" –

13
seq -s "*" 1 500 |bc 
+1

Và btw. điều này không hoạt động trên Mac OSX hoặc bất kỳ hệ thống nào khác không đi kèm với lõi của GNU (mà seq là một phần của) –

+0

sau đó sử dụng jot trên Mac OS. Nếu có hệ thống nào khác – ghostdog74

2

Dưới đây là một hàm đệ quy trong Bash:

factorial() { 
    if (($1 == 1)) 
    then 
     echo 1 
     return 
    else 
     echo $(($(factorial $(($1 - 1))) * $1)) 
    fi 
} 

Tất nhiên nó khá chậm và hạn chế.

1

Có một số ví dụ hướng dẫn on Rosetta Code.

Dưới đây là một tôi thấy đặc biệt hữu ích:

function factorial { 
    typeset n=$1 
    ((n < 2)) && echo 1 && return 
    echo $((n * $(factorial $((n-1))))) 
} 
0

Tôi gần như hoàn toàn đồng ý với Vitalii Fedorenko, tôi sẽ giống như paxdiablo gợi ý sử dụng bc, đây là mã từ Vitalii Fedorenko nhưng sửa đổi để sử dụng bc.

#!/bin/bash 
counter=$1 
output=1 
while [ $counter -gt 1 ] #while counter > 1 (x*1=x) 
do 
     output=$(echo "$output * $counter" | bc) 
     counter=$(($counter - 1)) 
done 
#remove newlines and '\' from output 
output=$(echo "$output" | tr -d '\' | tr -d '\n') 
echo "$output" 
exit 

Phương pháp này là tốt hơn bởi vì bc cho phép bạn sử dụng chuỗi, thay vì số nguyên, làm cho nó có thể cho bạn để tính toán số lớn hơn nhiều.

Tôi xin lỗi nếu tôi không sử dụng chính xác tr, tôi không quen thuộc lắm.

0
seq -s* `dd`|bc 

Tôi tin rằng đây là cách ngắn nhất để hoàn thành tác vụ.

0

Bạn có thể sử dụng:

seq -s "*" 1 10 | sed 's/*$//g' |bc 

trên mac

Các vấn đề liên quan