bc에서 후행 0을 인쇄하는 방법은 무엇입니까?

bc에서 후행 0을 인쇄하는 방법은 무엇입니까?

나는 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; …

관련 정보