Python 寻找从a到b不能被x到y整除的数

Python 寻找从a到b不能被x到y整除的数,python,math,set,division,modulo,Python,Math,Set,Division,Modulo,这是一个我思考了很长时间的问题 找到从a到b的所有不能被从x到y的任何数字整除的数字的最快方法是什么 考虑这一点: 我想找出从1到10的所有数字,它们不能被2到5整除。 如果我使用线性方法,这个过程将变得非常缓慢; 像这样: result = [] a = 1 b = 10 x = 2 y = 5 for i in range(a,b): t = False for j in range(x,y): if i%j==0: t = True

这是一个我思考了很长时间的问题

找到从a到b的所有不能被从x到y的任何数字整除的数字的最快方法是什么

考虑这一点:

我想找出从1到10的所有数字,它们不能被2到5整除。 如果我使用线性方法,这个过程将变得非常缓慢; 像这样:

result = []
a = 1
b = 10
x = 2
y = 5
for i in range(a,b):
    t = False
    for j in range(x,y):
        if i%j==0:
            t = True
            break
    if t is False:
        result.append(i)
return result
有人知道有没有比线性解计算时间更短的其他方法

如果不是的话,有人能看到如何更快地完成这项工作吗,因为我目前还处于空白状态

真诚地, 约翰

[编辑]

数字的范围为0到>1,e+100


这对于a、b、x和y是正确的,您只需要检查可能的除数范围内的素数值-例如,如果一个值不能被2整除,它也不能被2的任何倍数整除;对于其他素数和素数倍数也是如此。因此,在您的示例中,您可以检查
2,3,5
——您不需要检查
4
,因为任何可以被4整除的东西都必须可以被2整除。因此,一种更快的方法是在您感兴趣的任何范围内计算素数,然后简单地计算它们除以哪些值

另一种加速方法是将感兴趣的范围内的每个值添加到
集合中:当您发现该值可被范围内的数字整除时,请将其从集合中删除。然后,您应该只测试保留在集合中的数字-这将阻止您多次测试数字

如果我们将这两种方法结合起来,我们可以创建一个所有值的
(因此在本例中,一个所有值为1到10的集),然后简单地从该集中删除第二个范围内每个素数的倍数

编辑:正如Patashu指出的,如果除掉给定值的素数不在集合中,这将不太有效。为了解决这个问题,我们可以对上面的问题应用一个类似的算法:创建一个
集合
,其值
[a,b]
,对于
集合中的每个值,删除其所有倍数。因此,对于下面注释中给出的示例(使用
[3,6]
),我们将从3开始,并删除集合中的倍数-So
6
。因此,我们需要测试的剩余值将是
[3,4,5]
,这就是我们在本例中想要的

Edit2:这是一个非常糟糕的实现,没有经过优化,变量名非常糟糕:

def find_non_factors():
    a = 1
    b = 1000000
    x = 200
    y = 1000

    z = [True for p in range(x, y+1)]
    for k, i in enumerate(z):
        if i:
            k += x
            n = 2
            while n * k < y + 1:
                z[(n*k) - x] = False
                n += 1

    k = {p for p in range(a, b+1)}

    for p, v in enumerate(z):
        if v:
            t = p + x
            n = 1
            while n * t < (b + 1):
                if (n * t) in k:
                    k.remove(n * t)
                n += 1

    return k
def find_non_factors():
a=1
b=1000000
x=200
y=1000
z=[范围(x,y+1)内的p为真]
对于k,i在枚举(z)中:
如果我:
k+=x
n=2
当n*k

使用这些数字尝试您的原始实现。在我的电脑上花费>1分钟。此实现只需2秒钟。

最终优化警告:不要提前优化。每当您尝试优化代码时,请对其进行分析,以确保它需要优化,并对您希望优化的同一类数据进行分析,以确认它是一种加速。几乎所有代码都不需要优化,只是为了给出正确的答案

如果要针对小x-y和大a-b进行优化:

创建一个长度为所有x,x+1,x+2中最小公倍数的数组。。。Y例如,对于2,3,4,5,它将是60,而不是120

现在用布尔值填充此数组-最初每个单元格为false,然后对于x-y中的每个数字,用true填充数组中该数字的倍数的所有条目

现在,对于a-b中的每个数字,索引到数组modulo arraylength中,如果为true,则跳过else,如果为false,则返回

通过从x到y因子中移除素数因子展开式是其他数的素数因子展开式的严格超集的数,可以更快地实现这一点。我的意思是,如果你有2,3,4,5,4是2*2,一个严格的超集2,你可以去掉它,现在我们的数组长度只有30。对于像3,4,5,6这样的东西,4是2*2,6是3*2-6是3的超集,所以我们去掉它,但是4不是所有的超集,所以我们保留它。LCM为3*2*2*5=60。对于大型a-b来说,这样做可以自己提高一些速度,如果您只需要这样做的话,您可能不需要按照阵列方向进行操作


另外,请记住,如果您不打算每次都使用函数的整个结果(比如,有时您可能只对最低值感兴趣),请将其作为生成器而不是函数编写。这样,您就可以呼叫它,直到您有足够的号码,然后停止,从而节省时间。

您是在优化大(b-a)、大b、大(y-x)、大y,还是在使用小号码多次呼叫它?我怀疑答案会因问题的一部分而有所不同:a,b,x,y,逐渐增长你不想写1e100而不是“1,e+100”吗?如果是这种情况,那么就很难找到一个非常快速的方法,因为这组数字不适合内存,甚至不适合硬盘(到目前为止)。如果数字计数是合理的(比如1e8,这样它们就适合内存),那么可以通过用内存换取速度来获得快速方法。这不是真的,例如7*11不能被2、3、4或5整除,但它也不是素数。@Patashu你误解了我说的话(尽管我同意我没有把它说得那么好)。我的意思是,在一个范围内,比如说
[2,5]
你只需要测试
2,3,5
——测试
2
将测试
4