다음 bash 스크립트가 있습니다
# 1 + x^2/2! + x^4/4! + ... + x^(2n)/(2*n)!
#!/bin/bash
factorial() {
n=$1
fact=1
for ((i = 2; i <= $n; i++)); do
fact=$(expr $fact \* $i)
done
return $fact
}
read -p "x = " x
read -p "n = " n
sum=0
for ((i = 1; i <= n; i++)); do
val=$((2 ** ($i - 1)))
ex=$(($x ** $val))
f=$(factorial $val)
a=$(($ex / $f))
sum=$(($sum + $a))
done
echo $sum
위의 시리즈를 구현하려고합니다. 해결책이 필요하지 않습니다. 왜 오류가 발생하는지 이해가 되지 않습니다.
실수:
x = 1
n = 2
sum_of_series.sh: line 20: 1 / : syntax error: operand expected (error token is "/ ")
답변1
a=$(($ex / $f))
(나누기) 연산자 뒤에 피연산자가 없기 때문에 오류 메시지가 줄로 인해 발생합니다 . /
따라서 변수 f
가 빈 문자열인지 즉시 의심됩니다.
그 이유는 $( )
할당 시 명령 대체 동작 때문입니다. f
이는 닫힌 명령 파이프라인을 실행할 때 stdout의 내용을 수집합니다. 함수 factorial()
가 표준 출력에 아무 것도 쓰지 않으므로 f에 할당된 값은 비어 있습니다. 해결책은 대신 값을 에코하거나 인쇄하는 것입니다 return
(예: ) printf '%s\n' "${fact}"
.
도움이 될 수 있는 추가 참고 사항:
return 문의 값은 함수가 생성할 수 있는 데이터가 아니라 함수의 상태를 나타냅니다. return 문이 없으면 함수에서 실행된 마지막 명령의 종료 상태가 호출자에게 다시 전달됩니다.
반환 상태는 8비트로 잘리고 부호가 없으므로 0-255 범위만 사용할 수 있습니다.
또한 외부 명령의 상태에 대한 추가 규칙이 있습니다. 시그널에 의해 종료된 프로세스의 상태는 128 + 시그널 번호입니다. 셸이 새 프로세스를 생성하거나 명령을 실행할 수 없으면 126 또는 127을 반환할 수 있습니다. 상태 0은 일반적으로 성공을 나타내며, 1부터 시작하는 작은 정수는 명령에 의해 감지된 오류 또는 비정상적인 결과를 나타냅니다. 쉘 함수에서도 동일한 규칙을 따르고 절대 이런 식으로 데이터 값을 반환하지 않는 것이 현명하다고 생각합니다.
쉘 연산(GNU/bash 매뉴얼에 따름)은 고정 너비 정수에 대한 계산을 수행합니다. 내 시스템에서는 이 값이 64비트 부호 있는 정수로 보이지만 시스템과 배포판에 따라 다를 수 있습니다. 31비트는 12!만 저장할 수 있고 63비트는 20!만 저장할 수 있으므로 범위가 제한될 수 있습니다.
이 스니펫은 Bash 산술이 약 9.22e+18에서 63비트를 오버플로함을 보여줍니다.
Paul--) for k in {1..10}; do
> printf '%s %s\n' $k $(( 3000000000000000000 * k ))
> done
1 3000000000000000000
2 6000000000000000000
3 9000000000000000000
4 -6446744073709551616
5 -3446744073709551616
6 -446744073709551616
7 2553255926290448384
8 5553255926290448384
9 8553255926290448384
10 -6893488147419103232
Paul--)
큰 숫자의 경우 첫 번째 선택은 숫자 크기를 무제한으로 허용하지만 RPN(역 폴란드 표기법)이 필요한 dc 명령입니다. 이 조각은 최대 10개의 계승을 나열하는 RPN 명령을 생성합니다!
Paul--) { echo 1; seq -s ' p * p ' 2 10; echo ' p * p q'; }
1
2 p * p 3 p * p 4 p * p 5 p * p 6 p * p 7 p * p 8 p * p 9 p * p 10
p * p q
Paul--)
실행 내용은 다음과 같습니다(그러나 최대 400개까지 테스트했습니다!).
Paul--) { echo 1; seq -s ' p * p ' 2 10; echo ' p * p q'; } | dc
2
2
3
6
4
24
5
120
6
720
7
5040
8
40320
9
362880
10
3628800
Paul--)