試した増分として0.02を使用してbashでforループを作成したいと思います。
for ((i=4.00;i<5.42;i+=0.02))
do
commands
done
しかし、成功しませんでした。
答え1
シェルでループを避けてください。
算術を実行するには、awk
次のようにしますbc
。
awk '
BEGIN{
for (i = 4.00; i < 5.42; i+ = 0.02)
print i
}'
または
bc << EOF
for (i = 4.00; i < 5.42; i += 0.02) i
EOF
awk
(とは対照的にbc
)プロセッサに適用できる浮動小数点数値表現(double
おそらくIEEE 754タイプ)。したがって、この数字は10進数の2進近似であるため、驚くことがあります。
$ gawk 'BEGIN{for (i=0; i<=0.3; i+=0.1) print i}'
0
0.1
0.2
1つを追加すると、OFMT="%.17g"
欠落している理由を確認できます0.3
。
$ gawk 'BEGIN{OFMT="%.17g"; for (i=0; i<=0.5; i+=0.1) print i}'
0
0.10000000000000001
0.20000000000000001
0.30000000000000004
0.40000000000000002
0.5
bc
任意の精度を持っているので、そのような問題はありません。
デフォルトでは、(出力形式を変更したり明示的な型指定をOFMT
使用しない限り)浮動小数点数を表示するために、1,000,000以上の浮動小数点数は1e6以上に切り替わり、高い数字は小数部分(100000.02)が切り捨てられます。 100000と表示されます。)printf
awk
%.6g
たとえば、ループの各反復に対して特定のコマンドを実行するため、ループにシェルを使用する必要がある場合は、浮動小数点演算をサポートするシェルを使用するか、上記のいずれかのコマンドを使用zsh
して生成しますyash
。ksh93
値のリスト(またはseq
利用可能な場合)と出力を繰り返します。
良い:
unset -v IFS # configure split+glob for default word splitting
for i in $(seq 4 0.02 5.42); do
something with "$i"
done
または:
seq 4 0.02 5.42 | while IFS= read i; do
something with "$i"
done
プロセッサの浮動小数点数の制限を超えない限り、浮動seq
小数点近似によって発生したエラーは上記のバージョンよりもスムーズに処理されますawk
。
GNU コマンドがない場合は、seq
次のように、より安定した機能を作成できます。
seq() { # args: first increment last
bc << EOF
for (i = $1; i <= $3; i += $2) i
EOF
}
この場合、これはより効率的ですseq 100000000001 0.000000001 100000000001.000000005
。ただし、任意の高精度数値をサポートしていないコマンドに渡す場合は、あまり役に立ちません。
答え2
読書bash
マニュアルページ次の情報を考慮すると:
for (( expr1 ; expr2 ; expr3 )) ; do list ; done
expr1
まず、以下の算術評価で説明されている規則に従って算術式を評価します。 [...]
それから私達はこの部分を得ます。
算術評価
シェルは特定の状況で算術式の評価を可能にします(組み込みコマンドと算術拡張を参照)
let
。declare
オーバーフローを確認せずに固定幅整数で評価を行います。 [...]
for
したがって、整数以外の値を持つループは使用できないことが明らかです。
1つの解決策は、次のように、後で使用するためにすべてのループコンポーネントに100を掛けることです。
for ((k=400;k<542;k+=2))
do
i=$(bc <<<"scale=2; $k / 100" ) # when k=402 you get i=4.02, etc.
...
done
開始値と終了値の有効桁数が同じ場合(この場合は3つ)、bc
forループの各反復を呼び出さずに文字列処理を使用して10進値を生成できます。
i="${k%??}.${k#?}" # POSIX; when k=402 you get i=4.02, etc.
i="${k:0:1}.${k:1}" # bash; when k=402 you get i=4.02, etc.
答え3
「seq」を使用 - 一連の数字を印刷します。
seq 最初の増分最後
for i in $(seq 4.00 0.02 5.42)
do
echo $i
done
答え4
他の人が提案したように、bcを使用できます。
i="4.00"
while [[ "$(bc <<< "$i < 5.42")" == "1" ]]; do
# do something with i
i="$(bc <<< "$i + 0.02")"
done