285

0Bashスクリプトで2つの画像幅を分割しようとしていますが、結果としてbashが表示されます。

RESULT=$(($IMG_WIDTH/$IMG2_WIDTH))

私はBashガイドを研究しましたがbc、インターネットのすべての例で使用する必要があることを知っていますbc。でecho同じものを入れようとしましたSCALEが、うまくいきませんでした。

これが私がチュートリアルで見つけた例です:

echo "scale=2; ${userinput}" | bc 

どうすればBashにフロートのようなものを提供させることができ0.5ますか?

4

22 に答える 22

282

できません。bashは整数のみを実行します。などのツールに委任する必要がありbcます。

于 2012-10-04T07:18:10.933 に答える
233

あなたはこれを行うことができます:

bc <<< 'scale=2; 100/3'
33.33

更新 20130926:次を使用できます:

bc -l <<< '100/3' # saves a few hits
33.33333333333333333333
于 2012-10-04T08:32:51.187 に答える
177

bash

他の人が指摘しているように、bash浮動小数点演算はサポートされていませんが、小数点以下2桁など、固定の小数のトリックで偽造することはできます。

echo $(( 100 * 1 / 3 )) | sed -e 's/..$/.&/;t' -e 's/.$/.0&/'

出力:

.33

同様ですがより簡潔なアプローチについては、ニルフレッドの回答を参照してください。

代替案

上記bcおよびawk代替案に加えて、以下もあります。

clisp

clisp -x '(/ 1.0 3)'

クリーンアップされた出力:

clisp --quiet -x '(/ 1.0 3)'

またはを通じてstdin

echo '(/ 1.0 3)' | clisp --quiet | tail -n1

dc

echo 2k 1 3 /p | dc

天才CLI計算機

echo 1/3.0 | genius

ghostscript

echo 1 3 div = | gs -dNODISPLAY -dQUIET | sed -n '1s/.*>//p' 

gnuplot

echo 'pr 1/3.' | gnuplot

Imagemagick

convert xc: -format '%[fx:1/3]' info:

またはを通じてstdin

echo 1/3 | { convert xc: -format "%[fx:$(cat)]" info:; }

jq

jq -n 1/3

またはを通じてstdin

echo 1/3 | jq -nf /dev/stdin

ksh

echo 'print $(( 1/3. ))' | ksh

lua

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

perl

echo print 1/3 | perl

python2

echo print 1/3. | python2

python3

echo 'print(1/3)' | python3

R

echo 1/3 | R --no-save

クリーンアップされた出力:

echo 1/3 | R --vanilla --quiet | sed -n '2s/.* //p'

ルビー

echo puts 1/3.0 | ruby

単位

units 1/3

コンパクトな出力:

units --com 1/3

wcalc

echo 1/3 | wcalc

クリーンアップされた出力:

echo 1/3 | wcalc | tr -d ' ' | cut -d= -f2

zsh

print $(( 1/3. ))

またはを通じてstdin

echo 'print $(( 1/3. ))' | zsh

その他の情報源

StéphaneChazelas は、 ULに関する同様の質問に答えました。

于 2015-02-16T12:24:22.277 に答える
41

マーヴィンの答えを少し改善する:

RESULT=$(awk "BEGIN {printf \"%.2f\",${IMG_WIDTH}/${IMG2_WIDTH}}")

bcは、インストールされたパッケージとして常に提供されるわけではありません。

于 2014-03-14T13:21:03.480 に答える
34

-lオプション(L文字)でbcを使用できます

RESULT=$(echo "$IMG_WIDTH/$IMG2_WIDTH" | bc -l)
于 2013-03-27T16:58:43.800 に答える
29

bcの代わりに、スクリプト内でawkを使用できます。

例えば:

echo "$IMG_WIDTH $IMG2_WIDTH" | awk '{printf "%.2f \n", $1/$2}'

上記の「%.2f」は、printf関数に小数点以下2桁の浮動小数点数を返すように指示しています。awkが変数を適切に操作するため、echoを使用して変数をフィールドとしてパイプしました。「$1」と「$2」は、awkに入力される最初と2番目のフィールドを指します。

そして、以下を使用して結果を他の変数として保存できます。

RESULT = `echo ...`
于 2014-01-09T21:54:13.937 に答える
20

さて、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桁を取得します。

于 2016-02-15T06:15:06.680 に答える
19

浮動小数点演算を含む多くの優れた機能を備えた(ほぼ)bashスーパーセットであるzshを試すのに最適な時期です。zshでの例は次のようになります。

% IMG_WIDTH=1080
% IMG2_WIDTH=640
% result=$((IMG_WIDTH*1.0/IMG2_WIDTH))
% echo $result
1.6875

この投稿はあなたを助けるかもしれません:bash-カジュアルな使用のためにzshに切り替える価値がありますか?

于 2012-10-04T16:12:36.570 に答える
5

好みのバリアントを見つけた場合は、それを関数にラップすることもできます。

ここでは、いくつかのバシズムを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

更新 bashの浮動小数点数を使用した基本的な操作を提供する小さなスクリプトを追加しました。

使用法:

> add 1.2 3.45
4.65
> sub 1000 .007
999.993
> mul 1.1 7.07
7.7770
> div 10 3
3.
> div 10 3.000
3.333

そしてここにスクリプトがあります:

#!/bin/bash
__op() {
        local z=00000000000000000000000000000000
        local a1=${1%.*}
        local x1=${1//./}
        local n1=$((${#x1}-${#a1}))
        local a2=${2%.*}
        local x2=${2//./}
        local n2=$((${#x2}-${#a2}))
        local n=$n1
        if (($n1 < $n2)); then
                local n=$n2
                x1=$x1${z:0:$(($n2-$n1))}
        fi
        if (($n1 > $n2)); then
                x2=$x2${z:0:$(($n1-$n2))}
        fi
        if [ "$3" == "/" ]; then
                x1=$x1${z:0:$n}
        fi
        local r=$(($x1"$3"$x2))
        local l=$((${#r}-$n))
        if [ "$3" == "*" ]; then
                l=$(($l-$n))
        fi
        echo ${r:0:$l}.${r:$l}
}
add() { __op $1 $2 + ;}
sub() { __op $1 $2 - ;}
mul() { __op $1 $2 "*" ;}
div() { __op $1 $2 / ;}
于 2018-09-26T18:29:25.913 に答える
4

これは実際には浮動小数点ではありませんが、複数の結果を設定するものが必要な場合は、bcの1回の呼び出しになります...

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で与えられる円の面積と直径を計算します

于 2014-01-18T16:58:26.417 に答える
4

bcは、busyboxや組み込みシステムの一部のカットダウンバージョンのように、単に存在しない可能性があるため、使用できないシナリオがあります。いずれにせよ、外部依存関係を制限することは常に良いことです。そのため、(分子)で割る数に常にゼロを追加できます。これは、10の累乗を掛けるのと同じです(に応じて10の累乗を選択する必要があります。必要な精度)、それは除算出力を整数にします。その整数を文字列として扱い、小数点を(右から左に移動して)分子に掛けた10の累乗に等しい回数だけ配置します。これは、整数のみを使用して浮動小数点数の結果を取得する簡単な方法です。

于 2014-10-14T16:40:10.757 に答える
4

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))
于 2018-05-10T09:36:06.053 に答える
4

bashで浮動小数点計算を行う方法:

最も支持されている例の1つであるように、コマンドで「 herestrings」(<<<)を使用する代わりに、 manページのセクションからの私のお気に入りの浮動小数点の例を示します(マニュアルページを参照)。bcbcEXAMPLESbcman bc

始める前に、円周率の方程式は次のとおりであることを知っておいてくださいpi = 4*atan(1)a()以下はのbc数学関数ですatan()

  1. これは、浮動小数点計算の結果をbash変数(この場合は。)と呼ばれる変数に格納する方法ですpiscale=10この場合、精度の小数点以下の桁数を10に設定することに注意してください。この場所の後の10進数はすべて切り捨てられます。

     pi=$(echo "scale=10; 4*a(1)" | bc -l)
    
  2. ここで、この変数の値も出力する1行のコードを作成するにはecho、次のように、フォローアップコマンドとしてコマンドを最後に追加するだけです。次のように、小数点以下10桁の切り捨てに注意してください。

     pi=$(echo "scale=10; 4*a(1)" | bc -l); echo $pi
     3.1415926532
    
  3. 最後に、いくつかの丸めを入れましょう。ここでは、このprintf関数を使用して小数点以下4桁に丸めます。3.14159...に丸められることに注意してください3.1416scale=10四捨五入しているので、小数点以下10桁まで切り捨てる必要がなくなったので、その部分を削除します。最終的な解決策は次のとおりです。

     pi=$(printf %.4f $(echo "4*a(1)" | bc -l)); echo $pi
     3.1416
    

上記の手法のもう1つの非常に優れたアプリケーションとデモは、ランタイムの測定と印刷です。

ここで私の他の答えも参照してください)。

からにdt_min丸められることに注意してください:0.01666666666...0.017

start=$SECONDS; sleep 1; end=$SECONDS; dt_sec=$(( end - start )); dt_min=$(printf %.3f $(echo "$dt_sec/60" | bc -l)); echo "dt_sec = $dt_sec; dt_min = $dt_min"
dt_sec = 1; dt_min = 0.017

関連している:

于 2019-10-21T04:36:24.670 に答える
4

受け入れられた答えでパーセンテージを計算しようとしているが、精度を失っている人のために:

これを実行する場合:

echo "scale=2; (100/180) * 180" | bc

あなた99.00だけが得ます、それは精度を失っています。

このように実行すると、次のようになります。

echo "result = (100/180) * 180; scale=2; result / 1" | bc -l

今、あなたは得る99.99

印刷の瞬間にのみスケーリングしているからです。

こちらをご覧ください

于 2020-04-30T17:09:37.053 に答える
3

私はそれが古いことを知っていますが、あまりにも魅力的です。だから、答えは:あなたはできません...しかし、あなたは一種のことができます。これを試してみましょう:

$IMG_WIDTH=1024
$IMG2_WIDTH=2048

$RATIO="$(( IMG_WIDTH / $IMG2_WIDTH )).$(( (IMG_WIDTH * 100 / IMG2_WIDTH) % 100 ))"

このように、ポイントの後に2桁の数字が表示され、純粋なbash(他のプロセスを起動する必要はありません)で切り捨てられます(下に丸められます)。もちろん、ポイントの後に1桁しか必要ない場合は、10を掛けて、10を法とします。

これは何をしますか:

  • 最初$((...))に整数除算を行います。
  • 2番目$((...))は、100倍大きいもので整数除算を行い、基本的に2桁をポイントの左側に移動し、(%)モジュロを実行してそれらの2桁のみを取得します。

ボーナストラックbcバージョン×1000は私のラップトップで1.8秒かかりましたが、純粋なbashものは0.016秒かかりました。

于 2019-07-22T19:05:13.120 に答える
2

calcを使用します。これは私が見つけた最も簡単な例です:

計算1+1

 2

計算1/10

 0.1
于 2019-06-11T19:14:15.740 に答える
1

**bash/シェルでのインジェクションセーフな浮動小数点演算**

注:この回答の焦点は、bash(または他のシェル)で数学を実行するためのインジェクションセーフソリューションのアイデアを提供することです。もちろん、高度な文字列処理などを実行するために微調整を加えて、同じものを使用することもできます。

提示されたソリューションのほとんどは、外部データ(変数、ファイル、コマンドライン、環境変数)を使用して、その場で小さなスクリプトレットを作成します。外部入力を使用して、悪意のあるコードをエンジンに挿入することができます。その多くは

以下は、さまざまな言語を使用して基本的な数学計算を実行する場合の比較です。結果は浮動小数点になります。A + B * 0.1(浮動小数点として)を計算します。

すべてのソリューションの試みは、保守が非常に難しい動的スクリプトレットの作成を避け、代わりに静的プログラムを使用して、指定された変数にパラメーターを渡します。特殊文字を含むパラメーターを安全に処理し、コードインジェクションの可能性を減らします。例外は、入出力機能を提供しない「BC」です。

例外は「bc」です。これは入出力を提供せず、すべてのデータはstdinのプログラムを介して送られ、すべての出力はstdoutに送られます。すべての計算はサンドボックスで実行されているため、副作用(ファイルを開くなど)は発生しません。理論的には、注射は設計上安全です!

A=5.2
B=4.3

# Awk: Map variable into awk
# Exit 0 (or just exit) for success, non-zero for error.
#
awk -v A="$A" -v B="$B" 'BEGIN { print A + B * 0.1 ; exit 0}'

# Perl
perl -e '($A,$B) = @ARGV ; print $A + $B * 0.1' "$A" "$B"

# Python 2
python -c 'import sys ; a = float(sys.argv[1]) ; b = float(sys.argv[2]) ; print a+b*0.1' "$A" "$B"

# Python 3
python3 -c 'import sys ; a = float(sys.argv[1]) ; b = float(sys.argv[2]) ; print(a+b*0.1)' "$A" "$B"

# BC
bc <<< "scale=1 ; $A + $B * 0.1"
于 2019-12-02T15:09:47.630 に答える
1

配当=除数×商+剰余

商と余りを計算してみましょう。また、これらの文字列を変数に連結します。

bar=1234 \
&& divisor=1000 \
    && foo=$(printf "%s.%s" $(( bar / divisor )) $(( bar % divisor ))) \
    && printf "bar is %d miliseconds or %s seconds\n" $bar $foo

出力:bar is 1234 miliseconds or 1.234 seconds

于 2021-12-21T12:58:05.697 に答える
0

ここにawkコマンドがあります:-F=フィールド区切り文字==+

echo "2.1+3.1" |  awk -F "+" '{print ($1+$2)}'
于 2019-02-18T16:36:46.273 に答える
0

他の人が示しているように、bashには浮動小数点演算子が組み込まれていません。

bcawkなどの計算機プログラムやその他の外部プログラムを使用しなくても、bashに浮動小数点を実装できます。

私は自分のプロジェクトであるshellmathで、これを3つの基本的なステップで正確に実行しています。

  1. 数値を整数部分と小数部分に分解します
  2. 組み込みの整数演算子を使用して、場所の値と持ち運びに注意しながら、パーツを個別に処理します
  3. 結果を再結合する

ティーザーとして、x=0を中心とするテイラー級数を使用してeを計算するデモスクリプトを追加しました。

時間があればチェックしてください。フィードバックをお待ちしております。

于 2020-12-03T12:20:16.677 に答える
0

出力をどの程度正確にする必要がありますか?ビニングによる近似がユースケースですでに受け入れられている場合は、さらに一歩進んでPOSIX終了コード[0:256)を利用することもできます(他のすべての整数はその範囲に戻されます)。

例:gawk / nawk / mawk-1では、すでに整数レベルまでエポック秒が表示されますが、ミリ秒に近い精度を抽出するために拡張したかったのですが、過度に衒学的ではありません。このコマンドをPOSIXシェルで実行します。

exit $(( 10#` gdate +%5N ` * 256 / 100000 ))

0.xxxxxxgnu-dateの出力を表す5桁の整数を256個のビンの1つに直接割り当て、256awkがsystem()呼び出しの終了コード(選択されたビン番号)を取得したら、それを元に戻します。このアプローチでは、完全なgetline呼び出しを使用するよりもオーバーヘッドが少ないことがわかりました。

このメソッドは、追加の端末を印刷する代わりに、出力をPOSIX終了コードに直接キャプチャします。

auto floors it to integer( * 0.0256の代わりにこのように記述された場合のシェル演算)。awk関数にまとめると、これに似ています。これ10#は、「01733」を8進数として解釈するposixシェルを防ぐために基数10を強制することです。

function msecs() {     # n x 2**-8 = n divided by 256

    return 2^-8 * \
           system( "exit \44\50\50 "      \
                   " 10\43\140 gdate \53"  \
                   "%5N\140 \52 " \
                   "256 \57 100000 \51\51" )
}
  • 私自身のコードでは、シェルのオーバーヘッドを考慮して、さらに0.6%のヘアカットを適用します。
于 2021-10-20T08:00:39.673 に答える
0

Bashは、他のプログラムがなくても浮動小数点の結果をうまく計算できます。

Bashは独立して、小数点以下9桁までのπを正確に計算することもできます。

例:

calc=104348/33215

accuracy=9

calc99p9=$((10**$accuracy))*$calc
result99p9=$((calc99p9))
result=${result99p9: -${#result99p9}: -$accuracy}.${result99p9: -$accuracy}

echo Bash calculated pi to be $result

結果は

Bash calculated pi to be 3.141592653
于 2022-01-28T20:49:16.827 に答える