Bashスクリプトで2つの画像幅を分割しようとしていますが、結果としてbashは0
を返します。
RESULT=$(($IMG_WIDTH/$IMG2_WIDTH))
私はBashガイドを勉強しました、そして私は私がbc
を使うべきであることを知っています、彼らがbc
を使うインターネットのすべての例で。 echo
では、SCALE
に同じことを入れようとしましたが、うまくいきませんでした。
これが私がチュートリアルで見つけた例です:
echo "scale=2; ${userinput}" | bc
どうやってBashから0.5
のようなフロートをもらうことができますか?
できません。 bashのみは整数を処理します。あなたはbc
のようなツールに委任しなければなりません。
あなたはこれを行うことができます:
bc <<< 'scale=2; 100/3'
33.33
UPDATE20130926
:あなたは使うことができます:
bc -l <<< '100/3' # saves a few hits
他の人が指摘したように、bash
は浮動小数点演算をサポートしていません。小数点以下2桁で
echo $(( 100 * 1 / 3 )) | sed 's/..$/.&/'
出力:
.33
似ているがより簡潔なアプローチについては、 Nilfredの答え を参照してください。
上記のbc
およびawk
の選択肢に加えて、次のものもあります。
clisp -x '(/ 1.0 3)'
クリーンアップされた出力付き:
clisp --quiet -x '(/ 1.0 3)'
またはstdinを通じて:
echo '(/ 1.0 3)' | clisp --quiet | tail -n1
echo 2k 1 3 /p | dc
echo 1/3.0 | genius
echo 'pr 1/3.' | gnuplot
echo 1/3 | jq -nf /dev/stdin
または
jq -n 1/3
echo 'print $(( 1/3. ))' | ksh
lua -e 'print(1/3)'
またはstdinを通じて:
echo 'print(1/3)' | lua
echo '1/3,numer;' | maxima
クリーンアップされた出力付き:
echo '1/3,numer;' | maxima --quiet | sed -En '2s/[^ ]+ [^ ]+ +//p'
echo 1/3 | node -p
echo 1/3 | octave
echo print 1/3 | Perl
echo print 1/3. | python2
echo 'print(1/3)' | python3
echo 1/3 | R --no-save
クリーンアップされた出力付き:
echo 1/3 | R --Vanilla --quiet | sed -n '2s/.* //p'
echo print 1/3.0 | Ruby
echo 1/3 | wcalc
クリーンアップされた出力では:
echo 1/3 | wcalc | tr -d ' ' | cut -d= -f2
echo 'print $(( 1/3. ))' | zsh
units 1/3
コンパクトな出力
units --co 1/3
StéphaneChazelasがUnix.SXで同様の質問 に答えました。
Marvinの答えを少し改善する:
RESULT=$(awk "BEGIN {printf \"%.2f\",${IMG_WIDTH}/${IMG2_WIDTH}}")
bcは常にインストール済みパッケージとして来るわけではありません。
-l
オプション(b文字)でbcを使うことができます
RESULT=$(echo "$IMG_WIDTH/$IMG2_WIDTH" | bc -l)
Bcの代わりに、あなたのスクリプトの中でawkを使うことができます。
例えば:
echo "$IMG_WIDTH $IMG2_WIDTH" | awk '{printf "%.2f \n", $1/$2}'
上記の "%.2f"は、小数点以下2桁の浮動小数点数を返すようにprintf関数に指示します。 awkがそれらに対して正しく動作するので、私はechoを使って変数をフィールドとしてパイプインしました。 "$ 1"と "$ 2"は、awkに入力された最初と2番目のフィールドを参照します。
そして結果を他の変数として保存することができます。
RESULT = `echo ...`
浮動小数点演算を含む多くの追加機能を備えた(ほぼ)bashスーパーセットであるzshを試すのに最適な時期です。これがzshでの例です。
% IMG_WIDTH=1080
% IMG2_WIDTH=640
% result=$((IMG_WIDTH*1.0/IMG2_WIDTH))
% echo $result
1.6875
この記事はあなたを助けるかもしれません: bash - 何気ない用途にzshに切り替える価値はありますか?
まあ、floatの前に固定小数点論理が使用された時でした:
IMG_WIDTH=100
IMG2_WIDTH=3
RESULT=$((${IMG_WIDTH}00/$IMG2_WIDTH))
echo "${RESULT:0:-2}.${RESULT: -2}"
33.33
最後の行はbashimです。bashを使用していない場合は、代わりに次のコードを試してください。
IMG_WIDTH=100
IMG2_WIDTH=3
INTEGER=$(($IMG_WIDTH/$IMG2_WIDTH))
DECIMAL=$(tail -c 3 <<< $((${IMG_WIDTH}00/$IMG2_WIDTH)))
RESULT=$INTEGER.$DECIMAL
echo $RESULT
33.33
コードの背後にある理論的根拠は、除算の前に100を掛けて小数点以下2桁を得ることです。
実際には浮動小数点数ではありませんが、1回のbcの呼び出しで複数の結果を設定するものが必要な場合は...
source /dev/stdin <<<$(bc <<< '
d='$1'*3.1415926535897932384626433832795*2
print "d=",d,"\n"
a='$1'*'$1'*3.1415926535897932384626433832795
print "a=",a,"\n"
')
echo bc radius:$1 area:$a diameter:$d
半径が$ 1で与えられる円の面積と直径を計算します
ビジーボックスの一部のバージョンや組み込みシステムのように、bcが存在しない場合があるため、bcを使用できないシナリオがあります。どんな場合でも、外部の依存関係を制限することは常に良いことです。(分子)で割った数に常にゼロを加えることができます。これは、10のべき乗を掛けるのと同じです。あなたが必要とする精度)、それは除算を整数にします。整数が文字列として扱われたら、小数点の位置を(右から左に移動させて)10の累乗に等しい回数にします(分子を掛けたもの)。これは、整数のみを使用してfloatの結果を取得する簡単な方法です。
あなたがあなたの好みの変種を見つけたなら、あなたはそれを関数にラップすることもできます。
ここで私はdiv関数にいくつかのバシズムを包んでいます:
ワンライナー:
function div { local _d=${3:-2}; local _n=0000000000; _n=${_n:0:$_d}; local _r=$(($1$_n/$2)); _r=${_r:0:-$_d}.${_r: -$_d}; echo $_r;}
または複数行:
function div {
local _d=${3:-2}
local _n=0000000000
_n=${_n:0:$_d}
local _r=$(($1$_n/$2))
_r=${_r:0:-$_d}.${_r: -$_d}
echo $_r
}
今、あなたは機能を持っています
div <dividend> <divisor> [<precision=2>]
そしてそれを好きに使う
> div 1 2
.50
> div 273 123 5
2.21951
> x=$(div 22 7)
> echo $x
3.14
私はそれが古いことを知っていますが、あまりにも魅力的です。そのため、答えは次のとおりです。これを試してみましょう:
$IMG_WIDTH=1024
$IMG2_WIDTH=2048
$RATIO="$(( IMG_WIDTH / $IMG2_WIDTH )).$(( (IMG_WIDTH * 100 / IMG2_WIDTH) % 100 ))
このように、ポイントの後に2桁の数字を取得し、純粋なbashで切り捨てられます(下への丸めと呼びます)(他のプロセスを起動する必要はありません)。もちろん、ポイントの後に1桁しか必要としない場合は、10を掛けて10を法とします。
これが何をするのか:
ボーナストラック:bcバージョンx 1000はラップトップで1,8秒かかりましたが、bashの場合は0,016秒かかりました。
Bashでは浮動小数点除算は使用できませんが、固定小数点除算は使用できます。あなたがする必要があるのはあなたの整数に10のべき乗を掛け、それから整数部分を分割し、小数部分を得るためにモジュロ演算を使用することです。必要に応じて丸めます。
#!/bin/bash
n=$1
d=$2
# because of rounding this should be 10^{i+1}
# where i is the number of decimal digits wanted
i=4
P=$((10**(i+1)))
Pn=$(($P / 10))
# here we 'fix' the decimal place, divide and round tward zero
t=$(($n * $P / $d + ($n < 0 ? -5 : 5)))
# then we print the number by dividing off the interger part and
# using the modulo operator (after removing the rounding digit) to get the factional part.
printf "%d.%0${i}d\n" $(($t / $P)) $(((t < 0 ? -t : t) / 10 % $Pn))
Calcを使用してください。これは私が見つけた最も簡単な例です。
計算1 + 1
2
計算1/10
0.1
これがawkコマンドです。-F =フィールド区切り文字== +
echo "2.1+3.1" | awk -F "+" '{print ($1+$2)}'