bashの浮動小数点数

bashの浮動小数点数

変数があり、ここに1000を掛けて5つの有効数字を印刷したいとします。zsh次のことができます。

zsh$ x=2.8026407e+00
zsh$ printf "%.5g\n" "$(( 1000*${x} ))"
zsh> 2802.6

それもできますかbash

bash$ x=2.8026407e+00
bash$ printf "%.5g\n" "$(( 1000*${x} ))"
bash> bash: 1000*2.8026407e+00 : syntax error: invalid arithmetic operator (error token is ".8026407e+00 ")

ネイティブbashに浮動小数点演算を理解させる方法はないと思います。そうですか? egを使用できることを知っていますが、これが可能かどうかをawk知りたいです。bash

bash(フロートを処理できないというのは驚きではありませんが、zsh処理されます!)

答え1

bash浮動小数点演算の代わりに小数点がゼロに固定される固定小数点演算(つまり整数演算)を実行します。これはあなたを意味しますできるこれに対して非常に基本的な計算を行います。

$ a=1;b=3
$ echo $(( (a*1000 / b ) ))
333

したがって、1/3〜3桁は0.333です。

これは悪い考えです。

コマンドラインでFP数学計算を実行する方法はいくつかあります。以下は2つの例です。

$ python -c 'print( 1.0 / 3 )'
0.333333333333
$ echo 'scale=3; 1.0/3' | bc
.333

答え2

bash小数点数学演算は実行できず、整数演算のみ実行できます。

robert@pip2:/tmp$ echo $((2 * 3))
6
robert@pip2:/tmp$ echo $((2 * 3.5))
bash: 2 * 3.5: syntax error: invalid arithmetic operator (error token is ".5")
robert@pip2:/tmp$ 

答え3

はい、ダッシュと同様に、bashは実際にはデフォルトですべてのシェル(デフォルトのPOSIX)は37を印刷します$((…))

$ echo "$((1000/27))"
37

[POSIX][1]から:

符号付きの長い算術だけが必要です。

ksh、zsh、yash(jsh、dash、ash、lksh、mksh、bashを除く)から浮動小数点数学を得るには、数字を少し変更する必要があります。

$ echo $((1000/27.0))
37.037037037037037

しかし、zshの優先順位と精度に注意してください。

$ for sh in ksh yash zsh; do $sh -c 'printf "%20d\n" "$(( 1<<63 - 5))"'; done
  288230376151711744
  288230376151711744
 9223372036854775803

$ for sh in ksh yash zsh; do $sh -c 'printf "%-20s\n" "$((1/10.0))"'; done
0.1                 
0.1                 
0.10000000000000001

予期しないzsh切り捨て制限:

$ zsh -c 'echo $((12345678901234567890));echo $((12345678901234567890123))'

zsh:1: number truncated after 19 digits: 12345678901234567890
1234567890123456789

zsh:1: number truncated after 22 digits: 12345678901234567890123
-1363962815083169260

bashにはprintf関数を使用する回避策があります(〜10桁に制限されています)。

$ bash -c 'printf "%.10f\n" "$(( 10**10*  1000/27  ))e-10"'
37.0370370370

しかし、bc利用可能なものがありますが、なぜ面倒ですか?

$ echo '1000/27' | bc -l
37.03703703703703703703

[1]: 符号付き長い算術だけが必要です。

答え4

特に bash は使用しませんが、次のものを使用できる必要がありますbc

# bc doesn't like exponential numbers in the manner provided.  It can be done, but this number is equivalent.
x=2.8026407
printf "1000 * %s" "$x" | bc

関連情報