私はbcに最初のゼロを出力させる方法についてのトピックを読みましたが、それは私が望んでいるものとは正確には異なります。私がもっと欲しい...
10進数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
が返されたときにこれらすべての0を保持する必要があります。現在、これが発生すると、このコードは次の出力を返します。
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
助けていただければ幸いです!
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のスケールを(bc -lから)20にし、bcへの1回の呼び出しで必要なすべての計算を行い、必要に応じてprintf
で出力をフォーマットすることです。はいprintf
は浮動小数点数をフォーマットできます。
Bashを想定
_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"
}
_
printf
を使用して、この方法でフォーマットを外部化できます。
printf "%0.8f" ${x}
例:
x=3
printf "%0.8f\n" ${x}
3.00000000
注:printf
出力は、ロケール設定によって異なります。
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
あなたの質問は少し曖昧です。あなたは「…これらすべての0を保持する必要がある…」と言います。 8桁の10進数で出力を取得する方法を説明した人もいます。しかし、入力値a
とb
がすでに持っている10進数を動的に決定しますか(同じ精度で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; …
_