python 浮点除法

2023-03-08,,

昨天晚上久违地去打了次div2

一年没打,挂得很惨

早上起来试着用python写一遍唯一写出来的a题

然后发现了一个奇怪的现象

代码如下(为了方便观察已经改过了,不是解题的代码)

import sys
x=1
y=100000000
k=100000000
a=k*y+k-1
ans=a/1
print(sys.maxsize)
print(int(a))
print(int(ans))

结果如下:

9223372036854775807
10000000099999999
10000000100000000

输出的第一行是int的最大值,是为了验证异常不是由于溢出导致的。

看到第二个输出,一个算是比较大的数字,第三个输出应当是其除以1的结果。

用小学生的脑子想一想,任意一个数字除以1结果应当不变吧。

但输出告诉我们,我不仅变,我还给你刚好+1。

但如果在这里使用整除的话,第二和第三个结果是一致的。

那么问题大约出在python的浮点除法的算法上了。

如果将除数改为2,可以看到第三个输出变为

5000000050000000

也就是说,在除法过程中依然出现了+1现象。

如果减小量级呢?

import sys
x=1
y=100000000
k=100000000
a=k+k-1
ans=a/1print(sys.maxsize)
print(int(a))
print(int(ans))

结果如下:

9223372036854775807
199999999
199999999

可以看到,+1现象消失了。

那么推测,+1现象的成因是在浮点运算中为了方便较大数字运算而引入的一个一般情况下可以忽略的填补量。

那么引入这个+1的临界范围是什么?

使用while循环,粗略地探究一下:

import sys
x=1
y=100000000
k=100000000
a=k+k-1
ans=a/1;
while a==ans:
print(int(a))
a*=10
ans=a/1print(sys.maxsize)
print(int(a))
print(int(ans))

结果是:

199999999
1999999990
19999999900
199999999000
1999999990000
19999999900000
199999999000000
1999999990000000
19999999900000000
199999999000000000
1999999990000000000
9223372036854775807
19999999900000000000
19999999900000002048

不对劲啊,为什么是在比int范围还有大的时候才跳出循环,明明之前产生偏差的数值比范围要小。

猜测,这个偏差的产生条件不只是数字的位数,还有其他的条件

观察最开始的那个数据,以及1的特殊性,猜测这个+1的偏差可能和数据的末尾9的个数有关

那么选取一个较小的9结尾的数字开始循环

import sys
a=199999
ans=a/1
while a==ans:
print(a)
a=a*10+9
ans=a/1
print(sys.maxsize)
print(int(a))
print(int(ans))

结果是:

199999
1999999
19999999
199999999
1999999999
19999999999
199999999999
1999999999999
19999999999999
199999999999999
1999999999999999
9223372036854775807
19999999999999999
20000000000000000

可以看到,位数与最初那个有偏差数据一样。

实验到此结束,暂时的结论是,在被除数大到一定程度(暂定17位)且末尾有一定数量9时,在除法运算中会进行一个+1

的填补以方便运算。

至于这个算法具体的优化过程不得而知,想来与现在的结论应该是大相径庭吧,只能留待日后有机会再研究了。

python 浮点除法的相关教程结束。

《python 浮点除法.doc》

下载本文的Word格式文档,以方便收藏与打印。