如何创建最紧凑的映射n→isprime(n)直到极限N?


152

自然地,因为bool isprime(number)会有可以查询的数据结构。
定义了最佳算法,该算法将生成在((1,N])范围内具有最低内存消耗的数据结构,其中N是常数。这
只是我要查找的示例:我可以表示每个奇数以一位为例,例如对于给定的数字范围(1,10],从3开始:1110

下面的字典可以压缩更多,对吧?我可以通过一些工作消除5的倍数,但是以1、3、7或9结尾的数字必须存在于位数组中。

我该如何解决这个问题?


3
您的要求有点含糊。您提供一个测试单个数字的签名,然后要求提供(1,N]的数据结构。您是否想要一种生成字典<int,bool>或仅检查单个数字的单次函数的算法是黄金?
Michael Haren

@Michael对不起,这是我能想到的最好的描述。我正在寻找的正是您所说的:一本布尔字典。我想最小化字典的空间。谢谢:)
AraK

1
如果这是你在找什么它已经已经问:stackoverflow.com/questions/1032427/...
奔小号

14
您需要询问国家安全局
Charles Bretana 09年

Answers:


79

进行素数测试的方法有很多。

确实没有要查询的数据结构。如果要测试的数字很多,则可能应该运行概率测试,因为这些测试速度更快,然后再进行确定性测试以确保数字为质数。

您应该知道,最快的算法背后的数学并不是为了胆小。


4
Miller-Rabin是一个流行的快速概率测试。
qwr

214

用于一般素数测试的最快算法是AKS。Wikipedia文章详细介绍了该文章,并链接到原始论文。

如果要查找大数,请查看具有特殊形式的素数,例如Mersenne素数

我通常实现的算法(易于理解和编码)如下(在Python中):

def isprime(n):
    """Returns True if n is prime."""
    if n == 2:
        return True
    if n == 3:
        return True
    if n % 2 == 0:
        return False
    if n % 3 == 0:
        return False

    i = 5
    w = 2

    while i * i <= n:
        if n % i == 0:
            return False

        i += w
        w = 6 - w

    return True

这是经典O(sqrt(N))算法的变体。它使用质数(2和3除外)为形式6k - 16k + 1仅查看此形式的除数的事实。

有时,如果我真的想要速度并且范围有限,我会根据费马小定理实施伪素数测试。如果我真的想要更高的速度(即完全避免使用O(sqrt(N))算法),则可以预先计算误报(请参阅Carmichael数)并进行二进制搜索。这是迄今为止我执行过的最快的测试,唯一的缺点是范围有限。


7
两个问题:您能否更好地解释变量iw是什么,以及形式6k-1和是什么意思6k+1?感谢您的见解和代码示例(我正试图理解)
Freedom_Ben 2014年

6
@Freedom_Ben在这里,quora.com /…
Alan Dong

6
那岂不是更好地计算出sqrtn一次,相比i于它,而不是计算i * i循环的每个周期?
佩德罗斯2015年

3
@Dschoni ...但是您不能在此处的评论字段中加入最快的实施方式与我们分享吗?
GreenAsJade '16

3
1号失败:(
Damjan Pavlica,

27

我认为最好的方法是使用以前的方法。

N互联网上有头等素数的清单,数量N至少可达五千万。下载文件并使用它们,它可能比您将想到的任何其他方法都快得多。

如果您想要一种用于生成自己的素数的实际算法,则Wikipedia在这里有关于素数的各种好东西,包括用于执行素数的各种方法的链接以及此处的素数测试,包括基于概率的方法和快速确定性方法。

应该齐心协力找到头十亿个(甚至更多)的素数,并将它们发布在网上某个地方,以便人们可以一遍又一遍地......-)


2
@hamedbh:有趣。您是否尝试下载这些文件?看来它们不存在。
paxdiablo

恐怕还没有呢:午休时间我只是在快速寻找。万一有恶意,我将删除该链接。很抱歉,我真的应该先检查一下。
哈默德

1
这样的清单确实存在。我几年前见过它们,但从未关心过下载它们。事实是,它们占用了大量空间(相对而言),不应包含在一个销售或分销的程序中。而且,它们将永远是永远不完整的。在程序使用过程中测试实际出现的每个数字确实更有意义,因为用这种方式测试的数字要少于您可能拥有的任何列表的长度。另外,我认为pax多数时候并没有意识到素数算法的目的是测试效率/速度,而不是实际找到素数。
CogitoErgoCogitoSum

2
@CogitoErgoCogitoSum,同意所有质数的列表将永远过时,因为我已经看到了数学上的证明,即它们的数量是无限的。但是,x一旦建成,第一个质数的列表就不太可能是不完整的:-)
paxdiablo

1
没错,但是比线性读取文件更好的存储方法。如果您真的想从一组预先生成的素数中读取数据,请尝试使用更复杂的数据结构来加快问题的速度。
CogitoErgoCogitoSum

10
bool isPrime(int n)
{
    // Corner cases
    if (n <= 1)  return false;
    if (n <= 3)  return true;

    // This is checked so that we can skip 
    // middle five numbers in below loop
    if (n%2 == 0 || n%3 == 0) return false;

    for (int i=5; i*i<=n; i=i+6)
        if (n%i == 0 || n%(i+2) == 0)
           return false;

    return true;
}

这只是上述AKS算法的 C ++实现


1
是的,它是Ive遇到的最有效的确定性算法之一,但不是AKS的实现。AKS系统比概述的算法要新得多。它可能更有效,但由于潜在的天文学上大的阶乘/二项式系数,很难实现。
CogitoErgoCogitoSum

这与Derri Leahi的(非)答案(用C代替Java)有什么不同?这个答案如何What is the algorithm that produces a data structure with lowest memory consumption for the range (1, N]
greybeard

1
(n%i == 0 || n%(i + 2)== 0)如何对应于6n + 1和6n-1?
yesh

@YeshwanthVenkatesh:How does (n%i == 0 || n%(i+2) == 0) correspond to 6n+1 & 6n-1?答案的一部分是针对的不同角色n,另一个是6n + 1和6n-1,相当于(6n-1)+0和(6n-1)+ 2 *。
灰胡子

另请注意,此算法无法为5和提供正确的结果7
凌晨

7

我比较了最流行的建议的效率,以确定数字是否为质数。我用python 3.6ubuntu 17.10; 我测试的数字最高为100.000(您可以使用下面的代码测试更大的数字)。

第一个图比较了这些函数(在我的答案中有进一步解释),表明当增加数字时,最后一个函数的增长速度不如第一个函数快。

情节1

在第二个图表中,我们可以看到在质数的情况下时间稳定增长,但是非质数的时间却没有那么快地增长(因为大多数可以在早期被消除)。

情节2

这是我使用的功能:

  1. 这个答案这个答案建议使用all()以下构造:

    def is_prime_1(n):
        return n > 1 and all(n % i for i in range(2, int(math.sqrt(n)) + 1))
    
  2. 这个答案使用了某种while循环:

    def is_prime_2(n):
        if n <= 1:
            return False
        if n == 2:
            return True
        if n == 3:
            return True
        if n % 2 == 0:
            return False
        if n % 3 == 0:
            return False
    
        i = 5
        w = 2
        while i * i <= n:
            if n % i == 0:
                return False
            i += w
            w = 6 - w
    
        return True
    
  3. 这个答案包括一个带有for循环的版本:

    def is_prime_3(n):
        if n <= 1:
            return False
    
        if n % 2 == 0 and n > 2:
            return False
    
        for i in range(3, int(math.sqrt(n)) + 1, 2):
            if n % i == 0:
                return False
    
        return True
    
  4. 然后,我将其他答案中的一些想法融合到一个新的答案中:

    def is_prime_4(n):
        if n <= 1:          # negative numbers, 0 or 1
            return False
        if n <= 3:          # 2 and 3
            return True
        if n % 2 == 0 or n % 3 == 0:
            return False
    
        for i in range(5, int(math.sqrt(n)) + 1, 2):
            if n % i == 0:
                return False
    
        return True
    

这是我用来比较变体的脚本:

import math
import pandas as pd
import seaborn as sns
import time
from matplotlib import pyplot as plt


def is_prime_1(n):
    ...
def is_prime_2(n):
    ...
def is_prime_3(n):
    ...
def is_prime_4(n):
    ...

default_func_list = (is_prime_1, is_prime_2, is_prime_3, is_prime_4)

def assert_equal_results(func_list=default_func_list, n):
    for i in range(-2, n):
        r_list = [f(i) for f in func_list]
        if not all(r == r_list[0] for r in r_list):
            print(i, r_list)
            raise ValueError
    print('all functions return the same results for integers up to {}'.format(n))

def compare_functions(func_list=default_func_list, n):
    result_list = []
    n_measurements = 3

    for f in func_list:
        for i in range(1, n + 1):
            ret_list = []
            t_sum = 0
            for _ in range(n_measurements):
                t_start = time.perf_counter()
                is_prime = f(i)
                t_end = time.perf_counter()

                ret_list.append(is_prime)
                t_sum += (t_end - t_start)

            is_prime = ret_list[0]
            assert all(ret == is_prime for ret in ret_list)
            result_list.append((f.__name__, i, is_prime, t_sum / n_measurements))

    df = pd.DataFrame(
        data=result_list,
        columns=['f', 'number', 'is_prime', 't_seconds'])
    df['t_micro_seconds'] = df['t_seconds'].map(lambda x: round(x * 10**6, 2))
    print('df.shape:', df.shape)

    print()
    print('', '-' * 41)
    print('| {:11s} | {:11s} | {:11s} |'.format(
        'is_prime', 'count', 'percent'))
    df_sub1 = df[df['f'] == 'is_prime_1']
    print('| {:11s} | {:11,d} | {:9.1f} % |'.format(
        'all', df_sub1.shape[0], 100))
    for (is_prime, count) in df_sub1['is_prime'].value_counts().iteritems():
        print('| {:11s} | {:11,d} | {:9.1f} % |'.format(
            str(is_prime), count, count * 100 / df_sub1.shape[0]))
    print('', '-' * 41)

    print()
    print('', '-' * 69)
    print('| {:11s} | {:11s} | {:11s} | {:11s} | {:11s} |'.format(
        'f', 'is_prime', 't min (us)', 't mean (us)', 't max (us)'))
    for f, df_sub1 in df.groupby(['f', ]):
        col = df_sub1['t_micro_seconds']
        print('|{0}|{0}|{0}|{0}|{0}|'.format('-' * 13))
        print('| {:11s} | {:11s} | {:11.2f} | {:11.2f} | {:11.2f} |'.format(
            f, 'all', col.min(), col.mean(), col.max()))
        for is_prime, df_sub2 in df_sub1.groupby(['is_prime', ]):
            col = df_sub2['t_micro_seconds']
            print('| {:11s} | {:11s} | {:11.2f} | {:11.2f} | {:11.2f} |'.format(
                f, str(is_prime), col.min(), col.mean(), col.max()))
    print('', '-' * 69)

    return df

运行该函数compare_functions(n=10**5)(最大数量为100.000),我得到以下输出:

df.shape: (400000, 5)

 -----------------------------------------
| is_prime    | count       | percent     |
| all         |     100,000 |     100.0 % |
| False       |      90,408 |      90.4 % |
| True        |       9,592 |       9.6 % |
 -----------------------------------------

 ---------------------------------------------------------------------
| f           | is_prime    | t min (us)  | t mean (us) | t max (us)  |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_1  | all         |        0.57 |        2.50 |      154.35 |
| is_prime_1  | False       |        0.57 |        1.52 |      154.35 |
| is_prime_1  | True        |        0.89 |       11.66 |       55.54 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_2  | all         |        0.24 |        1.14 |      304.82 |
| is_prime_2  | False       |        0.24 |        0.56 |      304.82 |
| is_prime_2  | True        |        0.25 |        6.67 |       48.49 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_3  | all         |        0.20 |        0.95 |       50.99 |
| is_prime_3  | False       |        0.20 |        0.60 |       40.62 |
| is_prime_3  | True        |        0.58 |        4.22 |       50.99 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_4  | all         |        0.20 |        0.89 |       20.09 |
| is_prime_4  | False       |        0.21 |        0.53 |       14.63 |
| is_prime_4  | True        |        0.20 |        4.27 |       20.09 |
 ---------------------------------------------------------------------

然后,运行该函数compare_functions(n=10**6)(最大为1.000.000),我得到以下输出:

df.shape: (4000000, 5)

 -----------------------------------------
| is_prime    | count       | percent     |
| all         |   1,000,000 |     100.0 % |
| False       |     921,502 |      92.2 % |
| True        |      78,498 |       7.8 % |
 -----------------------------------------

 ---------------------------------------------------------------------
| f           | is_prime    | t min (us)  | t mean (us) | t max (us)  |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_1  | all         |        0.51 |        5.39 |     1414.87 |
| is_prime_1  | False       |        0.51 |        2.19 |      413.42 |
| is_prime_1  | True        |        0.87 |       42.98 |     1414.87 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_2  | all         |        0.24 |        2.65 |      612.69 |
| is_prime_2  | False       |        0.24 |        0.89 |      322.81 |
| is_prime_2  | True        |        0.24 |       23.27 |      612.69 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_3  | all         |        0.20 |        1.93 |       67.40 |
| is_prime_3  | False       |        0.20 |        0.82 |       61.39 |
| is_prime_3  | True        |        0.59 |       14.97 |       67.40 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_4  | all         |        0.18 |        1.88 |      332.13 |
| is_prime_4  | False       |        0.20 |        0.74 |      311.94 |
| is_prime_4  | True        |        0.18 |       15.23 |      332.13 |
 ---------------------------------------------------------------------

我使用以下脚本来绘制结果:

def plot_1(func_list=default_func_list, n):
    df_orig = compare_functions(func_list=func_list, n=n)
    df_filtered = df_orig[df_orig['t_micro_seconds'] <= 20]
    sns.lmplot(
        data=df_filtered, x='number', y='t_micro_seconds',
        col='f',
        # row='is_prime',
        markers='.',
        ci=None)

    plt.ticklabel_format(style='sci', axis='x', scilimits=(3, 3))
    plt.show()


6

可以使用sympy

import sympy

sympy.ntheory.primetest.isprime(33393939393929292929292911111111)

True

来自sympy文档。第一步是寻找微不足道的因素,如果发现这些因素,便可以迅速获得回报。接下来,如果筛子足够大,请在筛子上使用二等分搜索。对于小数,使用已知范围内没有反例的碱基执行一组确定性Miller-Rabin测试。最后,如果该数字大于2 ^ 64,则执行强大的BPSW测试。尽管这是一个可能的主要测试,我们相信存在反例,但尚无已知的反例


算法是一系列定义明确的步骤,这些步骤定义了问题的抽象解决方案。-所呈现的代码中可能的步骤顺序是什么?它是什么memory consumption
灰胡子

2
@老人。来自sympy文档。第一步是寻找微不足道的因素,如果发现这些因素,便可以迅速获得回报。接下来,如果筛子足够大,请在筛子上使用二等分搜索。对于数量较少的情况,使用确定范围内没有反例的碱基执行一组确定性Miller-Rabin测试。最后,如果该数字大于2 ^ 64,则执行强BPSW测试。尽管这是一个可能的主要测试,并且我们相信存在反例,但尚无已知的反例。
LetzerWille

6

在Python 3中:

def is_prime(a):
    if a < 2:
        return False
    elif a!=2 and a % 2 == 0:
        return False
    else:
        return all (a % i for i in range(3, int(a**0.5)+1))

说明: 质数是只能被其自身和1整除的数字。例如:2,3,5,7 ...

1)如果a <2:如果“ a”小于2,则不是质数。

2)elif a!= 2和%2 == 0:如果“ a”可以被2整除,那么它绝对不是质数。但是,如果a = 2,我们不想对其进行评估,因为它是质数。因此条件a!= 2

3)返回all(range(3,int(a 0.5)+1)中i的i个%i):**首先看一下all()命令在python中的作用。从3开始,我们将“ a”除以其平方根(a ** 0.5)。如果“ a”是可分割的,则输出将为False。为什么是平方根?假设a = 16。16的平方根=4。我们不需要评估直到15。我们只需要检查直到4就可以说它不是素数。

额外: 一个循环,用于查找范围内的所有素数。

for i in range(1,100):
    if is_prime(i):
        print("{} is a prime number".format(i))

1
这与Oleksandr Shmyheliuk的答案有何不同?(都错过了range()……中的“第2步” )
灰胡子

1
如果数字是偶数,则不是质数(不包括2)。因此,无需检查偶数。如果要获得一定范围内的质数,则速度会更快。它将直接排除偶数。
深grew的人


3

对于大数,您不能简单地天真地检查候选数N是否可被除sqrt(N)之外的任何数整除。还有更多可扩展的测试,例如Miller-Rabin素数测试。下面有python实现:

def is_prime(x):
    """Fast implementation fo Miller-Rabin primality test, guaranteed to be correct."""
    import math
    def get_sd(x):
        """Returns (s: int, d: int) for which x = d*2^s """
        if not x: return 0, 0
        s = 0
        while 1:
            if x % 2 == 0:
                x /= 2
                s += 1
            else:
                return s, x
    if x <= 2:
        return x == 2
    # x - 1 = d*2^s
    s, d = get_sd(x - 1)
    if not s:
        return False  # divisible by 2!
    log2x = int(math.log(x) / math.log(2)) + 1
    # As long as Riemann hypothesis holds true, it is impossible
    # that all the numbers below this threshold are strong liars.
    # Hence the number is guaranteed to be a prime if no contradiction is found.
    threshold = min(x, 2*log2x*log2x+1)
    for a in range(2, threshold):
        # From Fermat's little theorem if x is a prime then a^(x-1) % x == 1
        # Hence the below must hold true if x is indeed a prime:
        if pow(a, d, x) != 1:
            for r in range(0, s):
                if -pow(a, d*2**r, x) % x == 1:
                    break
            else:
                # Contradicts Fermat's little theorem, hence not a prime.
                return False
    # No contradiction found, hence x must be a prime.
    return True

您可以使用它来查找巨大的质数:

x = 10000000000000000000000000000000000000000000000000000000000000000000000000000
for e in range(1000):
    if is_prime(x + e):
        print('%d is a prime!' % (x + e))
        break

# 10000000000000000000000000000000000000000000000000000000000000000000000000133 is a prime!

如果要测试随机整数,则可能需要先测试候选数是否可以被小于1000的任何质数整除,然后再致电Miller-Rabin。这将帮助您过滤掉明显的非质数,例如10444344345。


这是米勒测试。Miller-Rabin检验是概率版本,其中将测试随机选择的碱基,直到获得足够的置信度为止。而且,Miller检验不直接依赖于黎曼假设,而是针对二次Diriclet字符的广义黎曼假设(GRH)(我知道这是一个嘴,但我也不理解)。这意味着黎曼假说的潜在证据甚至可能不适用于GRH,因此无法证明Miller检验正确。如果GRH被拒,当然甚至更糟。
阿内·沃格尔

2

参加聚会太晚了,但希望对您有所帮助。如果您要寻找大的素数,则这是相关的:

要测试较大的奇数,您需要使用Fermat检验和/或Miller-Rabin检验。

这些测试使用相当昂贵的模幂运算,对于n位求幂,至少需要n大整数乘法和n大整数除法。这意味着模幂的复杂度为O(n³)。

因此,在使用大型机枪之前,您需要做很多试验。但是不要天真地做,有一种方法可以快速完成它们。首先将尽可能多的质数相乘成适合用于大整数的单词。如果使用32位字,请乘以3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 29 = 3234846615,并使用您使用欧几里德算法测试的数字计算最大公约数。第一步之后,将数字减少到单词大小以下,并继续执行算法,而不执行完整的大整数除法。如果GCD!= 1,则意味着您乘以的一个素数除以数字,因此您有证明它不是素数。然后继续31 * 37 * 41 * 43 * 47 = 95041567,依此类推。

一旦以这种方式测试了数百(或数千)个质数,就可以进行40轮Miller-Rabin测试以确认数字是质数,在40轮之后,您可以确定数字是质数,只有2 ^ -80的机会是不是(这很可能是您的硬件出现故障...)。


1

我有一个素数函数可以工作到(2 ^ 61)-1在这里:

from math import sqrt
def isprime(num): num > 1 and return all(num % x for x in range(2, int(sqrt(num)+1)))

说明:

all()函数可以重新定义为:

def all(variables):
    for element in variables:
        if not element: return False
    return True

all()函数只是通过一系列布尔值/数字,然后返回False0或False

sqrt()函数只是做一个数字的平方根

例如:

>>> from math import sqrt
>>> sqrt(9)
>>> 3
>>> sqrt(100)
>>> 10

num % x部分返回num / x 的余数

最后,range(2, int(sqrt(num)))意味着它将创建一个列表,该列表以2开始,以3结尾int(sqrt(num)+1)

有关范围的更多信息,请访问此网站

num > 1部分只是检查变量num是否大于1,因为1和0不被视为素数。

我希望这可以帮助:)


请争论这是什么the best算法,甚至是一个好的算法。
灰胡子

@greybeard,大多数质数函数在这里不会上升到(2 ^ 31)-1或花费太长时间以获得高数,但是我的函数会一直工作到(2 ^ 61)-1,因此您可以检查数字是否是较宽的素数数字范围。
WhyAreYouReading18年

1

在Python中:

def is_prime(n):
    return not any(n % p == 0 for p in range(2, int(math.sqrt(n)) + 1))

从数学形式主义到Python的更直接转换将使用all(n%p!= 0 ...),但这需要严格评估p的所有值。在没有任何如果真值,发现版本可以提前终止。


Wrt “ all(n%p!= 0 ...,但是需要对p的所有值进行严格评估”) -这是不正确的。any而且all都会提前退出。因此,在第一个p地方n % p0all将退出。
aneroid

1

素数javascript的最佳算法

 function isPrime(num) {
      if (num <= 1) return false;
      else if (num <= 3) return true;
      else if (num % 2 == 0 || num % 3 == 0) return false;
      var i = 5;
      while (i * i <= num) {
        if (num % i == 0 || num % (i + 2) == 0) return false;
        i += 6;
      }
      return true
    }

1
import math
import time


def check_prime(n):

    if n == 1:
        return False

    if n == 2:
        return True

    if n % 2 == 0:
        return False

    from_i = 3
    to_i = math.sqrt(n) + 1

    for i in range(from_i, int(to_i), 2):
        if n % i == 0:
            return False
    return True

1

质数是只能被1及其自身整除的任何数字。所有其他数字都称为Composite

查找质数的最简单方法是检查输入数字是否为复合数字:

    function isPrime(number) {
        // Check if a number is composite
        for (let i = 2; i < number; i++) {
            if (number % i === 0) {
                return false;
            }
        }
        // Return true for prime numbers
        return true;
    }

程序必须将数值除以number1到数值的整数。如果这个数字不仅可以被一个整数除以本身,那么它就是一个复合数字。

变量的初始值i必须为2,因为质数和复合数均可以均分1。

    for (let i = 2; i < number; i++)

然后i少于number出于相同的原因。质数和复合数都可以自己平均分配。因此,没有理由对其进行检查。

然后,我们检查变量是否可以使用余数运算符平均分配。

    if (number % i === 0) {
        return false;
    }

如果余数为零,则表示number可以平均除,因此是一个复合数并返回false。

如果输入的数字不符合条件,则表示它是质数,并且该函数返回true。


1
(虽然我认为simplest是对best的一种有效解释:)问题是检查数字是否为质数的最佳算法什么?:检查除数是否number / 2 < i < number有利?那number < i*i呢 其他3³答案中可以理解的是什么?
灰胡子

1

让我为您建议64位整数的完美解决方案。抱歉使用C#。您尚未在第一篇文章中将其指定为python。我希望您可以找到一个简单的modPow函数并轻松对其进行分析。

public static bool IsPrime(ulong number)
{
    return number == 2 
        ? true 
        : (BigInterger.ModPow(2, number, number) == 2 
            ? (number & 1 != 0 && BinarySearchInA001567(number) == false) 
            : false)
}

public static bool BinarySearchInA001567(ulong number)
{
    // Is number in list?
    // todo: Binary Search in A001567 (https://oeis.org/A001567) below 2 ^ 64
    // Only 2.35 Gigabytes as a text file http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
}

0

最小的内存?这不是最小的,但是是朝着正确方向迈出的一步。

class PrimeDictionary {
    BitArray bits;

    public PrimeDictionary(int n) {
        bits = new BitArray(n + 1);
        for (int i = 0; 2 * i + 3 <= n; i++) {
            bits.Set(i, CheckPrimality(2 * i + 3));
        }
    }

    public PrimeDictionary(IEnumerable<int> primes) {
        bits = new BitArray(primes.Max());
        foreach(var prime in primes.Where(p => p != 2)) {
            bits.Set((prime - 3) / 2, true);
        }
    }

    public bool IsPrime(int k) {
        if (k == 2) {
            return true;
        }
        if (k % 2 == 0) {
            return false;
        }
        return bits[(k - 3) / 2];
    }
}

当然,您必须指定的定义CheckPrimality


0

我认为最快的方法之一就是我的方法。

void prime(long long int number) {
    // Establishing Variables
    long long int i = 5;
    int w = 2;
    const long long int lim = sqrt(number);

    // Gets 2 and 3 out of the way
    if (number == 1) { cout << number << " is hard to classify. \n";  return; }
    if (number == 2) { cout << number << " is Prime. \n";  return; }
    if (number == 3) { cout << number << " is Prime. \n";  return; }

    // Tests Odd Ball Factors
    if (number % 2 == 0) { cout << number << " is not Prime. \n";  return; }
    if (number % 3 == 0) { cout << number << " is not Prime. \n";  return; }

    while (i <= lim) {
        if (number % i == 0) { cout << number << " is not Prime. \n";  return; }
        // Tests Number
        i = i + w; // Increments number
        w = 6 - i; // We already tested 2 and 3
        // So this removes testing multepules of this
    }
    cout << number << " is Prime. \n"; return;
}

1
一个错误可能是... 6-我?

0

与提到的AKS算法类似的想法

public static boolean isPrime(int n) {

    if(n == 2 || n == 3) return true;
    if((n & 1 ) == 0 || n % 3 == 0) return false;
    int limit = (int)Math.sqrt(n) + 1;
    for(int i = 5, w = 2; i <= limit; i += w, w = 6 - w) {
        if(n % i == 0) return false;
        numChecks++;
    }
    return true;
}

1
AKS算法无关。
灰胡子'18

在for循环中,您无需检查“ i <= limit”,就足以确认“ i <limit”。因此,在每次迭代中,您只需进行一次比较即可。
Andrushenko Alexander

0

要查找范围内的一个或多个数字是否为质数。

#!usr/bin/python3

def prime_check(*args):
    for arg in args:
        if arg > 1:     # prime numbers are greater than 1
            for i in range(2,arg):   # check for factors
                if(arg % i) == 0:
                    print(arg,"is not Prime")
                    print(i,"times",arg//i,"is",arg)
                    break
            else:
                print(arg,"is Prime")
                
            # if input number is less than
            # or equal to 1, it is not prime
        else:
            print(arg,"is not Prime")
    return
    
# Calling Now
prime_check(*list(range(101)))  # This will check all the numbers in range 0 to 100 
prime_check(#anynumber)         # Put any number while calling it will check.

运行此代码,它既适用于列表,也适用于特定号码
Harsh Singh,

0
myInp=int(input("Enter a number: "))
if myInp==1:
    print("The number {} is neither a prime not composite no".format(myInp))
elif myInp>1:
    for i in range(2,myInp//2+1):
        if myInp%i==0:
            print("The Number {} is not a prime no".format(myInp))
            print("Because",i,"times",myInp//i,"is",myInp)
            break
    else:
        print("The Number {} is a prime no".format(myInp))
else:
    print("Alas the no {} is a not a prime no".format(myInp))

1
当您写出答案时,即使答案正确,也请写些解释您在做什么以及原因。这样,人们阅读您的答案就可以更轻松地掌握您已解决的问题。谢谢!
kim,

1
当然,金,谢谢你指出这一点。这是我在Stackoverflow中的第一个程序,此后我将添加适当的注释和解释。
DKB

0
public static boolean isPrime(int number) {
 if(number < 2)
   return false;
 else if(number == 2 || number == 3)
        return true;
      else {
        for(int i=2;i<=number/2;i++)
           if(number%i == 0)
             return false;
           else if(i==number/2)
                return true;
      }
    return false;
}

0

您可以尝试这样的事情。

def main():
    try:
        user_in = int(input("Enter a number to determine whether the number is prime or not: "))
    except ValueError:
        print()
        print("You must enter a number!")
        print()
        return
    list_range = list(range(2,user_in+1))
    divisor_list = []
    for number in list_range:
        if user_in%number==0:
            divisor_list.append(number)
    if len(divisor_list) < 2:
        print(user_in, "is a prime number!")
        return
    else:
        print(user_in, "is not a prime number!")
        return
main()

这是测试素数的糟糕解决方案。找到一个除数后,您就知道了答案,但是此代码将找到所有除数,然后决定!并且它会始终返回OP忽略OP的布尔谓词请求None
cdlane

@cdlane我知道这不是布尔返回函数,我仍然是python的初学者,我知道它并不完美,无论如何感谢您的评论
Patrick Jane

0

先前的大多数答案都是正确的,但这是测试数字是否为质数的另一种方法。作为复习,素数是整数大于1的唯一因素是1和它本身。(来源

解:

通常,您可以建立一个循环并开始测试您的数字,以查看数字是否可以被1,2,3整除...最多可以测试的数字...等,但是为了减少检查时间,您可以将数字除以数字的一半,因为数字不能被其一半以上的值完全除尽。例如,如果您想看到100是质数,则可以循环查询最多50。

实际代码

def find_prime(number):
    if(number ==1):
        return False
    # we are dividiing and rounding and then adding the remainder to increment !
    # to cover not fully divisible value to go up forexample 23 becomes 11
    stop=number//2+number%2
    #loop through up to the half of the values
    for item in range(2,stop):
        if number%item==0:
           return False
        print(number)
    return True


if(find_prime(3)):
    print("it's a prime number !!")
else:
    print("it's not a prime")  

您只需要检查数字的平方根,它比数字的一半小得多。例如,对于n = 100,您只需要检查到10,而不是50。为什么?正好在平方根处,两个因子相等。对于任何其他因子,一个将小于sqrt(n),另一个更大。因此,如果在进行sqrt(n)之前的检查时还没有看到一个,那么以后将找不到一个。
DanaJ

0

我们可以使用Java流在O(sqrt(n))中实现它;考虑到noneMatch是一种shortCircuiting方法,当发现不需要用于确定结果的操作时,它将停止操作:

Scanner in = new Scanner(System.in);
int n = in.nextInt();
System.out.println(n == 2 ? "Prime" : IntStream.rangeClosed(2, ((int)(Math.sqrt(n)) + 1)).noneMatch(a -> n % a == 0) ? "Prime" : "Not Prime");

0

在Java-8流和lambda的帮助下,只需几行即可实现:

public static boolean isPrime(int candidate){
        int candidateRoot = (int) Math.sqrt( (double) candidate);
        return IntStream.range(2,candidateRoot)
                .boxed().noneMatch(x -> candidate % x == 0);
    }

性能应接近O(sqrt(N))。也许有人觉得它有用。


“ range”应替换为“ rangeClosed”以包含候选人根。同样应处理候选<2个案例。
udalmik

这与alirezafnatica的先前答案有何不同?
灰胡子

0

这是我对答案的看法:

def isprime(num):
    return num <= 3 or (num + 1) % 6 == 0 or (num - 1) % 6 == 0

如果以下任何属性为True,则该函数将返回True。这些属性在数学上定义了素数。

  1. 该数字小于或等于3
  2. 数字+1被6整除
  3. 数字-1可除以6

>>> isprime(25)返回True。您正在检查一个非常简单的必要条件(除以2或3),但这还不够
DanaJ

很好,您通过此属性进行匹配:大于3的每个素数都采用6n + 1或6n + 5的形式,但是存在数字(如25)采用6n + 1或6n + 5的形式,但是它们不是素数
Luis Felipe

0

当我必须进行快速验证时,我会根据低于输入平方根的数字之间的基本划分来编写此简单代码。

def isprime(n):
    if n%2==0:
        return n==2
    else:
        cota = int(n**0.5)+1
        for ind in range(3,2,cota):
            if n%ind==0:
                print(ind)
                return False
        return True != n==1

isprime(22783)
  • 最后True != n==1就是避免这种情况n=1

0
bool isPrime(int n) {
if(n <= 3)
    return (n > 1)==0? false: true;
else if(n%2 == 0 || n%3 == 0)
    return false;

int i = 5;

while(i * i <= n){
    if(n%i == 0 || (n%(i+2) == 0))
        return false;
    i = i + 6;
}

return true;
}

1
如果您使用edit在答案中添加了一些说明,那将更好。对于许多读者来说,可能还不清楚为什么您的答案是一个好的答案,如果您进一步解释,他们可以向您学习。
Brian Tompsett-汤莱恩
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.