まずは以下のプログラムを作ります。
a = 0
while a <= 10:
print("%d"%a)
a = a + 1
print()
b = 0.0
while b <= 1.0:
print("%f"%b)
b = b + 0.1
print()
c = 0.0
while c <= 1.0:
print("%.20f"%c)
c = c + 0.1
print()
するとこのように出力されます。
0
1
2
3
4
5
6
7
8
9
10
0.000000
0.100000
0.200000
0.300000
0.400000
0.500000
0.600000
0.700000
0.800000
0.900000
1.000000
0.00000000000000000000
0.10000000000000000555
0.20000000000000001110
0.30000000000000004441
0.40000000000000002220
0.50000000000000000000
0.59999999999999997780
0.69999999999999995559
0.79999999999999993339
0.89999999999999991118
0.99999999999999988898
普通に「%f」で出力すると0~1になっているように見えていますが、小数点以下20桁を出力するとそうならないことが分かります。
それもそのはずで、コンピュータは2進数、つまり「ON」と「OFF」です。
そうなると整数は問題ありませんが、小数点は表現できません。
例えばこれは10進数でも言えることで、「1÷3」は「0.3333…」となりますが、これが3進数だったら3の-1乗なので0.1になります。なので3進数ですから0.1+0.1+0.1=1となります。
で、2進数の話に戻りますが、2進数の小数点の表現は0.5、0.25、0.125…となっており、これらから表現しないといけませんので10進数を前提とした計算は難しいということが分かります。
そのため20桁で表現した結果、このようになります。
データサイエンスの世界でも教授から「桁数指定して精度をフルに出さなくてもええんやで」というお話がありましたが、この話を知れば納得すると思います。
という、タグでも書きましたが駆け出しエンジニアに伝えたい豆知識でした。
ちなみにですが、2進数の数値ならしっかり表現できます。
print("%.20f"%(0.5))
print("%.20f"%(0.25))
print("%.20f"%(0.125))
print("%.20f"%(0.0625))
print("%.20f"%(0.03125))
print("%.20f"%(0.015625))
0.50000000000000000000
0.25000000000000000000
0.12500000000000000000
0.06250000000000000000
0.03125000000000000000
0.01562500000000000000
まとめ
10進数のコンピュータできないかなw