新しい本を読むと知見が広がる
(2024/1/12改訂)森巧尚さんが書いた「ゲーム作りで楽しく学ぶPythonのきほん」という本を読んでいます。
本の中では当たり前と思われる誤差の話が出ていまして、「そういえば気にしてなかった!」と驚かされてます。
コンピューターなのに計算間違い?
たとえば「12.3+45,6」の計算をパイソンを使って実行してみましょう。少し不満足な結果が出てくるはずです。そんな所から話を始めたいと思います。
(私の確認した計算ミス)
パイソンに「100を3で割った結果を表示しなさい!!」とか
「12.3と45.6を足した値を表示しなさい!!」とか
入力してみたら妙な回答を出してきます。
これはコンピューター内の考え方が二進数で行われているためです。我々ば小学生の時に数学を習い始めて、その時以来あたり前に10の次は11だと思うのですが、コンピューターの中では
「我々の2」 が10で
「我々の4」 が100で
「我々の8」 が1000「だと考えています。
「我々の9」 が1001で、
「我々の10」 が1010で、
「我々の11」 が1011です。
「我々の12」 が1100で、
「我々の13」 が1101です。
こうした10進数か2進数かの差異があるので2進数で計算した結果を、また10進数にする時に「丸め誤差」というものが出てきて小数点以下最後の数字がズレます。
そんなものです。
100割る3
Pythonにおいて、整数どうしの割り算において誤差が生じることはありません。しかし、小数どうしの割り算や浮動小数点数の計算においては、誤差が生じる可能性があります。
具体的に上記の計算コードを実行すると、結果は次のように表示されます。
33.333333333333336
この結果は浮動小数点数として表現され、有限のビット数で実数を近似しているため、厳密な結果ではなく、少なからず誤差が生じています。このような誤差は、計算機の浮動小数点数表現の性質からくるものです。回避方法として「100/3」ではなくて「100//3」と記述すると厳密に整数部だけを出力します。
100割る3の整数部
具体的に、「100/3」ではなくて「100//3」と記述すると厳密に整数部だけを出力します。結果は次のようになります。具体的なコード例を以下に示します。
result = 100 // 3
print(result)
このコードを実行すると、整数部だけが出力されます。//
は整数の除算演算子であり、結果として整数部分が得られます。
上記のコードを実行すると、結果は 33
となります。
100割る3の余り
パイソンでの丸め誤差を回避するために整数部と余りで表示をすれば厳密な計算が続けられます。具体的に余りは次のように表記されます。
余りを表示する方法の一例です。
# 丸め誤差を回避するための整数部と余りでの計算の例
def divide_with_remainder(dividend, divisor):
quotient = dividend // divisor # 整数部
remainder = dividend % divisor # 余り
return quotient, remainder
# 例として 10 を 3 で割る場合
dividend = 10
divisor = 3
quotient, remainder = divide_with_remainder(dividend, divisor)
print(f”{dividend} を {divisor} で割ると 商: {quotient}, 余り: {remainder}“)
このコードでは、//
演算子で整数部を、%
演算子で余りを計算しています。これにより、浮動小数点数の丸め誤差を避けつつ、割り算の結果を整数部と余りとして取得することができます。
この手法は、特に金融や精密な計算が必要な場合に有用です。ただし、全てのケースでこの方法が適しているわけではないため、具体的な要件に基づいて使用するかどうかを検討する必要があります。
大きな数の計算が得意なPython
意外ですが、Pythonは大きな数の取り扱いが出来ます。例えば、以下の29桁の数字を考えても問題なく出力できます。
(私の出力)
こうした大きな数の足し算は計算機では扱えないほどなのですが、
Pythonの特性としては難なく計算が出来ます。凄いですね。
〆最後に〆
以上、間違い・ご意見は
次のアドレスまでお願いします。
最近は全て返信出来てませんが
適時、返信して改定をします。
nowkouji226@gmail.com
また、この記事はChatGPT社のOpenAI
の情報を参考として作成しています。
【全体の纏め記事へ】
コメント