나는 bc가 첫 번째 0을 인쇄하도록 하는 방법에 대한 스레드를 읽었지만 그것은 내가 원하는 것이 아닙니다. 내가 더 원해...
소수점 8자리의 부동 소수점 숫자를 반환하는 함수를 원합니다. 나는 awk 또는 다른 공정한 접근 방식을 사용하는 모든 솔루션에 열려 있습니다. 내가 의미하는 바를 설명하는 예는 다음과 같습니다.
hypothenuse () {
local a=${1}
local b=${2}
echo "This is a ${a} and b ${b}"
local x=`echo "scale=8; $a^2" | bc -l`
local y=`echo "scale=8; $b^2" | bc -l`
echo "This is x ${x} and y ${y}"
# local sum=`awk -v k=$x -v k=$y 'BEGIN {print (k + l)}'`
# echo "This is sum ${sum}"
local c=`echo "scale=8; sqrt($a^2 + $b^2)" | bc -l`
echo "This is c ${c}"
}
때로는 a
합계가 b
이고 반환 시 모든 0을 유지 0.00000000
해야 합니다 . c
현재 이런 일이 발생하면 이 코드는 다음 출력을 반환합니다.
This is a 0.00000000 and b 0.00000000
This is x 0 and y 0
This is c 0
나는 그것을 인쇄하고 싶다
This is a 0.00000000 and b 0.00000000
This is x 0.00000000 and y 0.00000000
This is c 0.00000000
도와주셔서 감사합니다!
답변1
bc에서 해는 1로 나누는 것입니다.
$ bc -l <<<"scale=8; x=25*20; x"
500
$ bc -l <<<"scale=8; x=25*20; x/1"
500.00000000
따라서 스크립트는 다음과 같을 수 있습니다.
hypothenuse () {
local a b c x y
a=${1}; b=${2}
echo "This is a ${a} and b ${b}"
x=$(echo "scale=8; $a^2/1" | bc -l)
y=$(echo "scale=8; $b^2/1" | bc -l)
echo "This is x ${x} and y ${y}"
# local sum=`awk -v k=$x -v k=$y 'BEGIN {print (k + l)}'`
# echo "This is sum ${sum}"
c=$(echo "scale=8; sqrt($a^2 + $b^2)/1" | bc -l)
echo "This is c ${c}"
}
$(…)
대신 사용하는 것이 좋습니다 `…`
.
그러나 이것조차도 값이 0이면 실패합니다.
가장 좋은 해결책은 bc에 20의 척도를 부여하고(bc -l에서) bc에 대한 단일 호출에 필요한 모든 수학을 수행한 다음 필요에 따라 출력 형식을 지정하는 것입니다 printf
. 예, printf
부동 소수점 형식을 지정할 수 있습니다.
배쉬를 가정
hypothenuse () { local a b c x y
a=${1:-0} b=${2:-0}
read -d '' x y c < <(
bc -l <<<"a=$a; b=$b; x=a^2; y=b^2; c=sqrt(x+y); x;y;c"
)
printf 'This is a %14.8f and b %14.8f\n' "$a" "$b"
printf 'This is x %14.8f and y %14.8f\n' "$x" "$y"
printf 'This is c %14.8f \n' "$c"
}
답변2
다음을 사용하여 형식을 외부화할 수 있습니다 printf
.
printf "%0.8f" ${x}
예:
x=3
printf "%0.8f\n" ${x}
3.00000000
참고: printf
출력은 로케일에 따라 다릅니다.
답변3
그냥 awk를 사용하세요:
$ cat tst.sh
#!/bin/env bash
hypothenuse() {
awk -v a="$1" -v b="$2" 'BEGIN {
printf "This is a %0.8f and b %0.8f\n", a, b
c = sqrt(a^2 + b^2)
printf "This is c %0.8f\n", c
}'
}
hypothenuse "$@"
$ ./tst.sh 0 0
This is a 0.00000000 and b 0.00000000
This is c 0.00000000
$ ./tst.sh 17.12 23.567
This is a 17.12000000 and b 23.56700000
This is c 29.12898709
답변4
귀하의 질문은 약간 모호합니다. 당신은 "...이 모든 것을 0으로 유지해야 합니다..."라고 말합니다. 다른 사람들은 십진수 8자리를 출력하는 방법을 알려 주었습니다. 그러나 입력 값 a
이 이미 가지고 있는 십진수 자릿수를 동적으로 확인하여 동일한 정밀도로 출력 b
할 수 있도록 하시겠습니까 ?c
Bash 내에서 이 작업을 수행할 수 있습니다.
a_digits=0
if [[ $a =~ \.([0-9]*)$ ]]
then
a_digits="${#BASH_REMATCH[1]}"
fi
b_digits=0
if [[ $b =~ \.([0-9]*)$ ]]
then
b_digits="${#BASH_REMATCH[1]}"
fi
=~
문자열을 정규식과 비교합니다. 정규식은 다음 \.([0-9]*)$
과 일치합니다..
그 뒤에는 그룹인 문자열 끝에 일련의 숫자가 옵니다.
BASH_REMATCH
전체 정규식 및 캡처 그룹(있는 경우)에 대한 일치 항목을 포함하는 배열입니다. 그렇다면 a
그렇습니다 3.1416
.BASH_REMATCH[1]
1416
그런 다음 a_digits
길이를 구하십시오 4
. 즉 .
bash가 없으면 다음 expr
과 같이 동일한 작업을 수행할 수 있습니다.
a_digits=$( expr length '(' "$a" : '.*\.\([0-9]*\)$' ')' )
b_digits=$( expr length '(' "$b" : '.*\.\([0-9]*\)$' ')' )
똑같은 논리입니다.
그러면 더 큰(최대) 값을 얻을 수 있습니다.
if [ "$a_digits" -gt "$b_digits" ]
then
digits="$a_digits"
else
digits="$b_digits"
fi
또는 그 반대로 더 작은(최소) 값을 얻으려면.
그런 다음 동적으로 결정된 이 정밀도를 다른 솔루션에서 사용할 수 있습니다.
printf "%0.${digits}f\n" "$c"
또는
printf '%0.*f\n' "$digits" "$c"
또는
…scale=$digits; …