根据素数创建网格

时间:2018-12-05 22:10:30

标签: python matplotlib primes

我正在绘制1,000 x 1,000的网格,其中白色正方形表示非质数,黑色正方形表示质数。

它应该看起来像是一个大网格,显示数字0-1,000,000并涂黑任何素数的正方形(因此,在第一个和第二个正方形上,它是白色(0和1),而第三个和第四个正方形是黑色( 2和3),等等)。一路上升到1,000,000

到目前为止,我的代码:

进口

from math import sqrt, ceil
import matplotlib.pyplot as plt
from matplotlib import colors
import numpy as np

生成素数列表

def all_prime(n):
    # https://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    """ Returns  a list of primes < n """
    sieve = [True] * n
    for i in range(3,int(n**0.5)+1,2):
        if sieve[i]:
            sieve[i*i::2*i]=[False]*((n-i*i-1)//(2*i)+1)
    return [2] + [i for i in range(3,n,2) if sieve[i]]

实际绘图

def prime_plot(n):
    '''
    Takes on argument (n), which is a number > 2 and produces a list of all primes up to n.
    Will then show on a plot the primes vs all numbers in range n.
    '''

    x = all_prime(n)
    y = list(range(n))

    data = np.random.rand(10, 10) * 20

    cmap = colors.ListedColormap(['white', 'black'])
    bounds = [0,10,20]
    norm = colors.BoundaryNorm(bounds, cmap.N)

    fig, ax = plt.subplots()
    ax.imshow(data, cmap=cmap, norm=norm)

    # draw gridlines
    ax.grid(which='major', axis='both', linestyle='-', color='k', linewidth=2)
    ax.set_xticks(np.arange(0, 10, 1));
    ax.set_yticks(np.arange(0, 10, 1));

    plt.show()

prime_plot(100)  

尽管我的意图是生成一个大小为m x m的网格(其中m为sqrt(len(n))),但我想从制作一个静态大小的网格开始。

如何修改上面的代码以创建所需的内容。大型网格看起来与matplotlib真的很杂乱。

更改数据以使用列表时,我收到TypeError:图像数据无法转换为浮点数

data = (x, y)

如何将x和y的列表转换为所需的列表(而不是随机生成的数字)?

3 个答案:

答案 0 :(得分:2)

我想这个想法是创建一个零数组(“非素数”的值),并将其中的那些值设置为1(如果您有素数)。然后,您需要将阵列重塑为NxN网格。

import matplotlib.pyplot as plt
import numpy as np

def all_prime(n):
    # https://stackoverflow.com/questions/2068372/fastest-way-to-list-all-
    #primes-below-n-in-python/3035188#3035188
    """ Returns  a list of primes < n """
    sieve = [True] * n
    for i in range(3,int(n**0.5)+1,2):
        if sieve[i]:
            sieve[i*i::2*i]=[False]*((n-i*i-1)//(2*i)+1)
    return [2] + [i for i in range(3,n,2) if sieve[i]]

def prime_plot(n):
    '''
    Takes on argument (n), which is a number > 2 and produces a list of all primes up to n.
    Will then show on a plot the primes vs all numbers in range n.
    '''
    N = int(np.sqrt(n))
    if N*N != n:
        raise ValueError("Need a square grid.")

    primes = np.array(all_prime(n)).astype(int)
    data = np.zeros(n)
    data[primes] = 1
    data = data.reshape(N,N)

    fig, ax = plt.subplots()
    ax.imshow(data, cmap="gray_r")

    for p in primes:
        ax.text(p%N, p//N, p, color="w", ha="center", va="center")

    plt.show()

prime_plot(100)

enter image description here

答案 1 :(得分:0)

  

与matplotlib一起使用时,大网格看起来真的很乱。

只是为了好玩,我决定尝试使用Python turtle实现您的程序。另外,为了进行编程实践,我将all_prime()变成了生成器:

from turtle import Screen, Turtle

LIMIT = 100
SQUARE_SIZE = 40

def all_prime(n):
    """ Returns  a list of primes < n """

    # https://stackoverflow.com/questions/2068372/fastest-way-to-list-all-
    # primes-below-n-in-python/3035188#3035188

    yield 2

    sieve = [True] * n

    for i in range(3, int(n ** 0.5) + 1, 2):
        if sieve[i]:
            sieve[i * i::2 * i] = [False] * ((n - i * i - 1) // (2 * i) + 1)

    yield from (i for i in range(3, n, 2) if sieve[i])

FONT_SIZE = SQUARE_SIZE // 2
FONT = ('Arial', FONT_SIZE, 'normal')
CURSOR_SIZE = 20
BORDER = SQUARE_SIZE
ROOT = int(LIMIT ** 0.5)

screen = Screen()
screen.setup(ROOT * SQUARE_SIZE + BORDER * 2, ROOT * SQUARE_SIZE + BORDER * 2)
screen.setworldcoordinates(-1, ROOT + 1, ROOT + 1, -1)

turtle = Turtle("square", visible=False)
turtle.penup()
turtle.goto((ROOT + 2) / 2 - 1, (ROOT + 2) / 2 - 1)

turtle.shapesize((ROOT * SQUARE_SIZE) / CURSOR_SIZE)
turtle.color("black", "white")
turtle.stamp()  # border

turtle.shapesize(SQUARE_SIZE / CURSOR_SIZE)
turtle.color("white", "black")

primes = all_prime(LIMIT)

try:
    prime = next(primes)

    for y in range(ROOT):

        if not prime:
            break

        for x in range(ROOT):

            if prime == (y * ROOT) + x:
                turtle.goto(x + 0.5, y + 0.5)
                turtle.stamp()

                turtle.sety(y + 0.5 + FONT_SIZE / SQUARE_SIZE / 2)
                turtle.write(prime, align="center", font=FONT)

                prime = next(primes)

except StopIteration:
    pass

screen.mainloop()

enter image description here

答案 2 :(得分:-1)

对于引物编号的生成,您可以使用eulerlib:https://pypi.org/project/eulerlib/ 该库在处理质数时非常有用。