数値とは
数値とは計算できる「数」のことです。 計算に使わない「数字」はプログラムの中では「文字列」として扱います。数値と文字列の違いについて,詳しくは こちらを参照してください。
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 進法表現
128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | |
例 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 1 |
例えば上記の「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 未満」の範囲の小数を表現できることになります。
1 | 0.5 | 0.25 | 0.125 | 0.0625 | 0.03125 | 0.015625 | 0.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 はお金を扱うような,高い精度が求められる計算に使われます。 しかし,計算処理速度が遅いというデメリットがあります。