4.1 浮動小数点数の丸め
浮動小数点数は英語でfloating point numberと言います。アメリカでは整数部と小数部の区切りにドットを使います。だからfloatという名前があります。
これまでの説明の通り、浮動小数点数(float)を整数(int)に変換すると、常に小数部が切り捨てられます。でも、小数点以下を単に最も近い整数に丸めたい場合があります。このような場合どうするのでしょう?
Pythonにはそのためにround()という組み込み関数があります。この関数は、mathライブラリが作られる前に考案されたので、mathライブラリには含まれていません。切り上げや切り捨ての関数はmathライブラリにあります。
round()関数は、数値を最も近い整数に丸めます:
round(浮動小数点数)
この関数は、渡された浮動小数点数に最も近い整数を返します。重要なのは、小数部が0.5の場合、round()関数は最も近い偶数の整数に丸めます。これは「銀行丸め」と呼ばれ、多くの丸めを行う際の系統的な誤差を減らすことができます。例えば:
例:
| コマンド | 結果 |
|---|---|
| x = round(4.1) | 4 |
| x = round(4.5) | 4 |
| x = round(4.9) | 5 |
| x = round(5.5) | 6 |
math.ceil()関数は、数値を切り上げて整数にします。例:
| コマンド | 結果 |
|---|---|
| x = math.ceil(4.1) | 5 |
| x = math.ceil(4.5) | 5 |
| x = math.ceil(4.9) | 5 |
math.floor()関数は、数値を切り下げて整数にします。例:
| コマンド | 結果 |
|---|---|
| x = math.floor(4.1) | 4 |
| x = math.floor(4.5) | 4 |
| x = math.floor(4.9) | 4 |
数値を切り下げるには型変換関数int()を使う方がシンプルです:
| コマンド | 結果 |
|---|---|
| x = int(4.9) | 4 |
これらのコマンドを覚えるのが難しい場合は、ちょっとした英語のレッスンが役立ちます:
math— 数学round— 丸めceiling— 天井floor— 床
4.2 浮動小数点数の仕組み
Pythonのfloatタイプは、-1.7*10308から+1.7*10308までの値を保持できます。この巨大な値の範囲は、floatタイプが整数タイプとは全く異なる構造になっているためです。float型の各変数は2つの数値を含んでいます:一つはマントと、もう一つは指数です。
例えば、我々が123456789という数を持っており、それをfloat型の変数に保存したとします。そうすると、その数は1.23456789*108の形に変換され、float型の内部では23456789と8の2つの数値が保持されます。赤で示されたのは「数の有効部分」(マント)で、緑は指数です。
このアプローチにより、非常に大きな数値や非常に小さな数値を保持できます。しかし、数値サイズが8バイト(64ビット)に制限されており、一部のビットは指数(および数の符号と指数の符号)を保持するために使用されるため、マントの最大長は15桁に制限されています。
これは浮動小数点数の仕組みを非常に簡単に説明したもので、もっと詳細なものは検索してみてください。
4.3 浮動小数点数の作業での精度喪失
浮動小数点数を扱う際には、浮動小数点数が不正確であることを常に意識する必要があります。常に丸め誤差、変換誤差があり、特に異なる桁数の数値の加算/減算による精度喪失が最も一般的です。
この最後のポイントは、プログラミング初心者にとって最も予期しない状況です。
109という数から1/109を引くと、再び109になります。
| 桁数の異なる数値の減算 | 説明 |
|---|---|
|
第2の数は小さすぎて、その有効部分が無視されます(灰色で示されています)。オレンジは15の有効桁です。 |
いやはや、プログラミングは数学とは違いますね。
4.4 浮動小数点数の比較の危険性
浮動小数点数の比較には他の危険があります。これらの数値を操作する際に丸め誤差が蓄積する可能性があるため、浮動小数点数が等しいはずなのに実際は等しくない場合や、逆に等しくないはずが等しい場合があります。
例:
| コマンド | 説明 |
|---|---|
| a = 1000000000.0 b = 0.000000001 c = a – b | 変数aには1000000000.0の値が入ります 変数cにも1000000000.0の値が入ります (変数bの数は小さすぎます) |
上記の例では、aとcは等しくないはずですが、等しいです。
また、別の例を見ましょう:
| コマンド | 説明 |
|---|---|
| a = 1.00000000000000001 b = 1.00000000000000002 | 変数aには1.0の値が入ります 変数bにも1.0の値が入ります |
実務では、浮動小数点数を次のように比較します:
とても小さな数値を設定し、差の絶対値がその数より小さい場合、それらの数は等しいとみなされます。例:
a = 0.00000000012
b = 0.000000000011
if abs(a - b) < 0.00001:
print("等しい")
else:
print("等しくない")
GO TO FULL VERSION