「0.2」は0.2より大きいか?

浮動小数点数IEEE 754)の話。倍精度で0.2は0.2より大きいだろうか。


print "%.17f" % 0.2 # 0.20000000000000001

すなわち、0.2より大きい。


0.2は内部ではどう表現されているだろうか。0.2を倍倍にしていってはじめて1以上になるのは、0.2->0.4->0.8->1.6だから、0.2は1.6×2-3で、仮数部の1.6から1を引いた0.6を52ビットで表す。


x = [ 6, 10 ]
s = "0."
for i in range(53):
x[0] += x[0]
if x[0] >= x[1]:
s += "1"
x[0] -= x[1]
else:
s += "0"
print s # 0.10011001100110011001100110011001100110011001100110011

53ビット目が1なので、恐らく切り上げが行われて、0.6より大きくなる。
これをまとめたのが下のコード。正の数のみ。実行例は次の通り。


> float 0.2
"0.2" is greater than 0.2.
0.20000000000000001000

> float 0.3
"0.3" is less than 0.3.
0.29999999999999999000



import sys

if len(sys.argv) != 2:
sys.exit(1)

x = [ 0, 1 ]
mode = 0
for c in sys.argv[1]:
if c.isdigit():
x[0] = x[0] * 10 + int(c)
if mode == 1:
x[1] *= 10
elif c == '.':
if mode == 0:
mode = 1
else:
sys.exit(1)
else:
sys.exit(1)

if x[0] < x[1]:
while x[0] < x[1]:
if (x[1] & 1) == 0:
x[1] >>= 1
else:
x[0] += x[0]
elif x[0] >= x[1] + x[1]:
while x[0] >= x[1] + x[1]:
if (x[0] & 1) == 0:
x[0] >>= 1
else:
x[1] += x[1]
x[0] -= x[1]

for i in range(52):
x[0] += x[0]
if x[0] >= x[1]:
x[0] -= x[1]
if x[0] == 0:
print "\"%s\"is equal to %s." % (sys.argv[1], sys.argv[1])
elif x[0] + x[0] >= x[1]:
print "\"%s\" is greater than %s." % (sys.argv[1], sys.argv[1])
else:
print "\"%s\" is less than %s." % (sys.argv[1], sys.argv[1])
print "%.20f\n" % float(sys.argv[1])