数値

数値とは

数値とは計算できる「数」のことです。 計算に使わない「数字」はプログラムの中では「文字列」として扱います。数値と文字列の違いについて,詳しくは こちらを参照してください。

Python で扱う数値データには,整数型と浮動小数点型があります。どちらも数値ですが,処理する内容によってデータ型を決めておきます。重さや気温・体温などは「36.4」のように少数点以下も表示する必要があるかもしれません。しかし,例えば金額などを算出して,「103.8」円などと表示されても困ってしまいます。そこで,「このデータは少数を扱う」,「このデータは整数のみを扱う」というように,プログラムの作成段階でデータの型を決めておいたほうが良いのです。整数型は「int(イント)型」(Integer の略),浮動小数点型は「float(フロート)型」といいます。

変数に数値を定義する

プログラム内でデータを扱うときには,別名を付けておくと処理の記述などがしやすくなります。この別名を変数といいます。 例えば「りんご」と「みかん」と「バナナ」の価格をそれぞれ表示するプログラムを書くとします。これらの価格にそれぞれ「ringo」「mikan」「banana」と別名を付けて価格データを定義してみましょう。

例. 変数に数値データを定義

ringo = 150
mikan = 80
banana = 200

それぞれの変数に価格が定義されました。この変数を使って,合計金額を計算してみましょう。

例. 変数を使って計算する

ringo = 150
mikan = 80
banana = 200
goukei = (ringo + mikan + banana)
print (goukei)

結果

430

数値の計算

数値データは数学と同じような計算ルールがあります。 詳しくは以下のリンクを参照してください。

四則演算

小数の計算誤差

「コンピュータは計算が早くて正確」というのは当然のような気がしますが,試しに以下の計算をしてみましょう。

print (0.1+0.2)

誰でもわかるかんたんな計算のようですが,プログラムを実行すると結果は以下のようになってしまいます。

0.30000000000000004

なぜこのようなことが起きるのでしょうか。

10 進法と 2 進法

コンピュータは私達人間が使う 10 進法ではなく,あらゆるデータを数字の「0」と「1」だけしか使わない2 進法で扱います。(電気信号の ON と OFF に置き換えられるからです。) 整数であれば,必要な bit 数があればどんな数でも 2 進法と 10 進法を正確に変換できます。

整数の 2 進法表現

27{2^7}26{2^6}25{2^5}24{2^4}23{2^3}22{2^2}21{2^1}20{2^0}
1286432168421
10100101

例えば上記の「10100101」という 8bit の 2 進法は,各 bit が表す数を足せば求められますから,10 進法に直すと「128+32+4+1」で「165」になります。 8bit の場合は 10 進法の 0〜255 まで表現できます。

小数の 2 進法表現 小数の 2 進法の場合,bit 数の中でどの桁までが整数でどこからが小数を表すかを決めます。小数の桁数をどれだけ取るかで精度が変わります。 例えば,8bit のうち 1 桁を整数部,残り 7 桁を小数部としてみましょう。 この場合,整数部は 1bit しかないので「0」か「1」しか表せず,10 進法の「0 以上 2 未満」の範囲の小数を表現できることになります。

20{2^0}21{2^{-1}}22{2^{-2}}23{2^{-3}}24{2^{-4}}25{2^{-5}}26{2^{-6}}27{2^{-7}}
10.50.250.1250.06250.031250.0156250.0078125

例えば「0.5」は 2 進法だと「0.1」と表わせます。 「0.75」は「0.5」の bit と「0.25」の bit を足せば良いので,2 進法だと「0.11」と表します。

でも,「0.1」を作り出すのは難しそうです。 0.125 の桁まではすでに 0.1 を超えているので,「0.000」の部分まではすぐにわかります。0.0625+0.03125=0.09375 です。この部分でまでで,2 進法だと「0.00011」です。 0.09375 に,次の桁の 0.015625 を足すと 0.1 を超えてしまうので次の桁は「0」で「0.000110」です。 こうやって実際に 10 進法の「0.1」に近づけようとしていくと, 「0.00011001100110011001……」と無限に続いてしまい,小数以下に何 bit 用意しようにも,10 進法の「0.1」ぴったりにはならないのです。 このように,10 進法の小数を 2 進法で表すと正確に表現できない場合が多いのです。 これは,コンピュータが 2 進法で動作している以上,どうしても起こってしまうことで,コンピュータの欠点と言えるかもしれません。 でも,よく考えると人間の世界でも,例えば円周率のように正確に 10 進法では表せない数値はたくさんあります。2 進法であれ,10 進法であれ,人間が考えたものですから,うまく表せない数があるのは仕方のないことなのです。

誤差による問題

小数の誤差は非常に小さいものですが,プログラム中に「何らかの処理の条件」としては使ったら間違いのもとになります。 例えば

例. 意図しない結果になってしまう

kotae = 0.1 + 0.2  # 0.1+0.2の結果をkotaeに代入する
if kotae == 0.3: #もしkotaeが0.3に等しければ
    print ('答えは0.3です。')  #条件が正しいときの処理
else:
    print('答えは0.3ではありません')  #条件と異なる時の処理

というプログラムを実行すると答えは0.3ではありませんと表示されてしまいます。これでは困ります。

小数の誤差を解消するには

小数の誤差を解消する方法はいくつかありますが,簡単なのは組み込み関数の round 関数を使って必要な桁数で丸めることです。 ただし通常の四捨五入とは異なりますので注意してください。 参考:Python 公式ドキュメント

以下の例では,小数第 1 位どうしの少数の計算を小数第 1 位に丸めています。一見無意味そうですが,これで誤差が丸められ,期待した結果が得られます。

例. round 関数を使う

kotae = round(0.1 + 0.2, 1)  #計算結果を小数第1位に丸める
if kotae == 0.3:
    print ('答えは0.3です。')
else:
    print('答えは0.3ではありません')

結果

答えは0.3です。

また,Decimal 関数を使う方法もあります。Decimal 関数は decimal モジュール内にありますので,import しておく必要があります。 decical とは「10 進法」のことです。

例. Decimal 関数を使う

データを 10 進法として定義するには,小数を「'」で囲み,文字列を Decimal 型に変換します。

import decimal
a = decimal.Decimal('0.1')   # 文字列'0.1'をDecimal型に変換する
b = decimal.Decimal('0.2')  # 文字列'0.1'をDecimal型に変換する
print (a+b)

結果

0.3

Decimal はお金を扱うような,高い精度が求められる計算に使われます。 しかし,計算処理速度が遅いというデメリットがあります。