如何将浮点数转换为分数/有理数

余生长醉 提交于 2020-02-27 05:04:02

问题的出处是某医院公布的一组数据,有 50 名患者,临床试验某种药剂后,52.4% 不咳嗽了,69.6% 乏力症状消失。问咳嗽的病人有几个,乏力的病人有几个,因为显然并不是所有病人都有这两种症状。

一开始因为分母不大,我使用穷举的方法求解,代码如下:

In [4]: for i in range(1, 51): 
   ...:     for j in range(1, 51): 
   ...:         if '%.3f' % (i / j) == '0.696':
   ...:             print(i, j) 

能够得到正确结果。但后来想这算法显然不行啊,有没有更好的计算方法呢?

首先想的是能不能从小数点后面的数字倒推分母,或者缩小分子分母的可能取值区间,因为每个素数分母能够产生的小数样式是有限的,即 n-1 个。但因为代数水平太低,不知道该怎么计算,最后可能还是会变成穷举或者查表法,就放弃了。

后来 google 了一下发现有个包叫 fractions,可以实现浮点数到分数的转换功能,在我实验的时候恰好看到了一组结果:

In [11]: Fraction(0.6959).limit_denominator()
Out[11]: Fraction(6959, 10000)

做这个实验是因为原本 69.6% 就是个约数,用这个包是算不出 50 以下的结果的,我就想试试自己添几位看能不能试出结果,没想到一下子试出一个素数,fractions 包给了我一个看起来很弱智的结果。但我突然想到,把小数简单乘 10 直到获得整数,再求最大公约数不就算出来了么。于是我的算法变成了:

In [14]: from math import gcd

In [15]: gcd(696, 1000)
Out[15]: 8

In [16]: 696/8
Out[16]: 87.0

In [17]: 1000/8
Out[17]: 125.0

最后我去看了一眼 fractions 的源码,开头就是一个

def gcd(a, b):
    """Calculate the Greatest Common Divisor of a and b.

看来通用的方法就是这么算的。

至于约数的问题,最后也没想出好办法。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!