シェル

シェル

数値に基づいて縦横比の高さを計算していますx。この例では、4:3の比率を使用し、幅は800です。結果(高さ)は600でなければなりませんが、bashは800を返しますが、その理由はわかりません。

他の言語を試してみましたが、ほとんど問題があるようです。 PHPは動作する数少ない言語の1つであるようです。

PHP(600リターン)

php -r 'echo 800/(4/3);'

Python(800リターン)

python -c "print(800/(4/3))"

bc -l少し動作します(600.00000000000000000150戻り)

-l「標準数学ライブラリ定義」です。どういう意味なのかわかりませんが、目標に近づくようです。しかし、追加の0と150はどこから来ますか?

echo '800 / (4 / 3)' | bc -l

私はこれが浮動小数点処理または切り捨てに関連していると推測します3/4

これで使用できますがphp、比較的簡単な計算にはやや過剰なようです。ここで何が起こっているのか知っていますか?

答え1

Bash算術は整数にのみ適用されます。したがって、4/3は1を返します。 800/1は800です。

入力を制御できる場合は、分割する前に再構成して乗算を実行できます。

$ echo $(( 800*3/4 ))
600

他の例も「整数」です。たとえば、4交換によってPythonを強制的に浮動状態にすると、4.0他の答えが得られます(Python 3ではこれを要求しません)。

$ python -c "print(800/(4.0/3))"
600.0

bc -l標準の数学ライブラリがロードされますが(s()サイン、l()自然ログなどの関数を含む)、より重要なのはscaleここで20に設定されることです。scale除算で下数を生成した後、小数点以下の桁数が何桁か定義するので(実際には)が4/3出て、これが出る理由を説明します。1.33333333333333333333133333333333333333333/1e+20600.00000000000000000150

echo 'scale=1000; 800/(4/3)' | bc

(数学ライブラリをロードせずに)より高い精度を提供しますが、10進数で表現できない600ため、目標に到達することはできません。4/3

答え2

シェル

一般的に言えば、シェルで一般的な数学演算を実行するには外部プログラムが必要です。

$ bc -l <<<'800/(4/3)'
$ bc -l <<<'scale=200;800/(4/3)'
$ awk 'BEGIN{print 800/(4/3)}'
$ awk 'BEGIN{printf "%.60f\n",800/(4/3)}'
$ python3 -c 'print(800/(4/3))'
$ python3 -c 'print(format(800/(4/3),".60f"))'

なぜ

これは2つの質問の共同結果です。

  • 個々のタスクは正しいです。
  • 作業順序。

個々の精度

整数で動作する場合、(4/3)値はです1

Pythonでも(Python 2は/「整数除算」を意味します):

$ python2 -c 'print(4/3)'
1

しかし、Python3ではそうではありません。

$ python3 -c 'print(4/3)'
1.3333333333333333

そのためaに800/(4/3)なり、800/1原因となります800。 (Python2から)

$ python2 -c 'print(800/(4/3))'
800

$ python3 -c 'print(800/(4/3))'
600.0

Bash(ほとんどのシェルと同様)はpython2(整数)に似ています。

$ bash -c 'echo (800/(4/3))'
800

注文する

整数変換の問題を防ぐために、数学の順序を変更できます。

$ python2 -c 'print(800*3/4)'
600

または、Pythonに浮動小数点数を使用するように指示します。

$ python2 -c 'print(800/(float(4)/3))'
600.0

限界

しかし、この数字を間違えないでください。精密。確かに次のように見えます:

python2 -c 'print(format(800/(4.0/3),".80f"))'
600.00000000000000000000000000000000000000000000000000000000000000000000000000000000

そして2^-50(または55)値は2進数で正確に表すことができます。

$ python2 -c 'print(format(2**-50,".80f"))'
0.00000000000000088817841970012523233890533447265625000000000000000000000000000000

$ python2 -c 'print(format(2**-55,".80f"))'
0.00000000000000002775557561562891351059079170227050781250000000000000000000000000

ただし、整数と浮動小数点を混合すると(または通常は数値計算を実行すると)、「範囲外」の結果が得られます。

$ python2 -c 'print(format(1 + 2**-50,".80f"))'
1.00000000000000088817841970012523233890533447265625000000000000000000000000000000

$ python2 -c 'print(format(1 + 2**-55,".80f"))'
1.00000000000000000000000000000000000000000000000000000000000000000000000000000000

通常、53桁の2進数を超える数字は、倍精度浮動小数点数字で切り捨てられます。

関連情報