bcで末尾のゼロを印刷する方法は?

bcで末尾のゼロを印刷する方法は?

私は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.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

あなたの質問は少しあいまいです。あなたは「...このすべてをゼロにしておく必要があります...」と言います。他の人は10進数8桁の出力方法を教えてくれました。しかし、入力値aがすでに持っている10進数を動的にチェックして、同じ精度で出力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]1416a_digits4

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

関連情報