如何从浮点列表中获取python中的公共整数?

时间:2016-04-11 14:20:28

标签: python list math int

我有浮动列表

l1 = [10.0, 50.0, 100.0]
l2 = [0.1, 0.5, 1.0]
l3 = [20.0, 100.0, 200.0]

所有人都应该回复:

i = [1, 5, 10]

最有效的方法是采用较小的作为基数的乘数?如果不可能,则为其中的一部分

示例:

n1 = [0.2, 0.3, 0.6]

应该返回

i = [2, 3, 6]

 n2 = [1424.56, 2136.84, 4985.96]

应该返回:

 i = [ 2, 3, 7] # 712.28 = 1

我使用的是value / min(l1),但它不适用于第二种情况和第三种情况

2 个答案:

答案 0 :(得分:4)

您可以将所有数字转换为整数,然后将每个数字除以greatest common divisor (GCD)。避免浮点数是一个好主意,因为它们无法准确表示多个小数。 fractions模块非常适用于此:它可以处理小数和有理数,如1/3和2/7。

#!/usr/bin/env python3

from fractions import Fraction, gcd
from functools import reduce

def lcm(a, b):
    return a * b // gcd(a, b)

def common_integer(*numbers):
    fractions = [Fraction(n).limit_denominator() for n in numbers]
    multiple  = reduce(lcm, [f.denominator for f in fractions])
    ints      = [f * multiple for f in fractions]
    divisor   = reduce(gcd, ints)
    return [int(n / divisor) for n in ints]

这将每个数字转换为理性fraction,然后将它们乘以其分母的最小公倍数(LCM)。这有效地扩展了它们,因此它们都是整数。然后它将它们除以它们的集体GCD,尽可能地缩小它们。

示例:

>>> common_integer('0.2', '0.3', '0.6')
[2, 3, 6]
>>> common_integer('1424.56', '2136.84', '4985.96')
[2, 3, 7]
>>> common_integer('2/7', '18/42', '1/3')
[6, 9, 7]

(使用limit_denominator()允许传入浮点数,即使是不精确的浮点值。不完全推荐它,但您可以省略引号并通过0.2代替{{1} }或'0.2'代替1/3。)

答案 1 :(得分:2)

在整数中,你正在寻找最大的公约数。有很多算法可以找到它。然后你需要将那个逻辑转移到浮点数,记住浮点运算意味着接近零的东西应该被认为是零:

#!/usr/local/bin/python3

from functools import reduce

def iszero(a):
    return abs(a)<1e-9

def gcd(a,b):
    if iszero(b):
        return a
    return gcd(b,a%b)

def gcdarr(arr):
    return reduce(gcd,arr)

def correctratios(arr):
    arrgcd = gcdarr(arr)
    return [round(a/arrgcd) for a in arr]

l = [.2,.3,.6]
n2 = [1424.56, 2136.84, 4985.96]

print(correctratios(l))
print(correctratios(n2))

打印出来:

[2, 3, 6]
[2, 3, 7]

Python 3.5引入了math.isclose,您可以使用它来代替iszero。它还将gcd从fractions移至math。内置gcd的问题在于它没有考虑浮点接近于零,并且一切都在爆炸。