1. 程式人生 > >python學習——練習題(12)

python學習——練習題(12)

fin ans 進行 根據 版權 set 如果 分布 while

"""
題目:判斷101-200之間有多少個素數,並輸出所有素數。
質數(prime number)又稱素數,有無限個。
質數定義為在大於1的自然數中,除了1和它本身以外不再有其他因數。
"""

import math


def answer1():
    """
    根據素數定義,一個一個判斷
    :return:
    """
    print("輸出一", end=":")
    sumCount = 0
    findTimes = 0
    for i in range(101, 2000):
        for j in range(2, i):
            findTimes += 1
            if i % j == 0:
                break
        else:
            print(i, end=",")
            sumCount += 1
    print("共%d個" % sumCount, end=",")
    print("共比較了%d次" % findTimes)


answer1()


def answer2():
    """
    上述判斷方法,明顯存在效率極低的問題。對於每個數n,其實並不需要從2判斷到n-1,我們知道,一個數若可以進行因數分解,
    那麽分解時得到的兩個數一定是一個小於等於sqrt(n),一個大於等於sqrt(n),據此,上述代碼中並不需要遍歷到n-1,遍歷到sqrt(n)即可,
    因為若sqrt(n)左側找不到約數,那麽右側也一定找不到約數。
    :return:
    """
    print("輸出二", end=":")
    sumCount = 0
    findTimes = 0
    for i in range(101, 2000):
        sqrtNum = int(math.sqrt(i))
        for j in range(2, sqrtNum + 1):
            findTimes += 1
            if i % j == 0:
                break
        else:
            print(i, end=",")
            sumCount += 1
    print("共%d個" % sumCount, end=",")
    print("共比較了%d次" % findTimes)


answer2()


def answer3():
    """
        方法(2)應該是最常見的判斷算法了,時間復雜度O(sqrt(n)),速度上比方法(1)的O(n)快得多。最近在網上偶然看到另一種更高效的方法,暫且稱為方法(3)吧,
    由於找不到原始的出處,這裏就不貼出鏈接了,如果有原創者看到,煩請聯系我,必定補上版權引用。下面講一下這種更快速的判斷方法;
    首先看一個關於質數分布的規律:大於等於5的質數一定和6的倍數相鄰。例如5和7,11和13,17和19等等;
    證明:令x≥1,將大於等於5的自然數表示如下:
    ······ 6x-1,6x,6x+1,6x+2,6x+3,6x+4,6x+5,6(x+1),6(x+1)+1 ······
    可以看到,不在6的倍數兩側,即6x兩側的數為6x+2,6x+3,6x+4,由於2(3x+1),3(2x+1),2(3x+2),所以它們一定不是素數,再除去6x本身,
    顯然,素數要出現只可能出現在6x的相鄰兩側。這裏有個題外話,關於孿生素數,有興趣的道友可以再另行了解一下,由於與我們主題無關,暫且跳過。
    這裏要註意的一點是,在6的倍數相鄰兩側並不是一定就是質數。
    根據以上規律,判斷質數可以6個為單元快進,即將方法(2)循環中i++步長加大為6,加快判斷速度,代碼如下:

    高手無處不在啊

    由上可得,只要從96開始,每6個計算一次
    :return:
    """
    print("輸出三", end=":")
    sumCount = 0
    findTimes = 0
    for i in range(102, 2000, 6):
        for num in (i - 1, i + 1):
            sqrtNum = int(math.sqrt(num))
            for j in range(2, sqrtNum + 1):
                findTimes += 1
                if num % j == 0:
                    break
            else:
                print(num, end=",")
                sumCount += 1
    print("共%d個" % sumCount, end=",")
    print("共比較了%d次" % findTimes)


answer3()


def answer4():
    """
    上面的方法,高手還可以改進
    因為上述可得,6x-1和6x+1坑定不會被6x,6x+2,6x+3,6x+4整除,弱它是素數,那麽它也是被6x-1或6x+1整除
    所以上面方法,裏面的判斷也可以跨6來判斷
    :return:
    """
    print("輸出四", end=":")
    sumCount = 0
    findTimes = 0
    for i in range(102, 2000, 6):
        for num in (i - 1, i + 1):
            sqrtNum = int(math.sqrt(num))
            for j in range(5, sqrtNum + 1, 6):
                findTimes += 1
                if num % j == 0 or num % (j + 2) == 0:
                    break
            else:
                print(num, end=",")
                sumCount += 1
    print("共%d個" % sumCount, end=",")
    print("共比較了%d次" % findTimes)


answer4()


def answer5():
    """
    排除偶數,數組統計
    :return:
    """
    print("輸出五", end=":")
    findTimes = 0
    numList = []
    for i in range(101, 2000, 2):
        numList.append(str(i))
        sqrtNum = int(math.sqrt(i))
        for j in range(2, sqrtNum + 1):
            findTimes += 1
            if i % j == 0:
                numList.pop()
                break
    print(",".join(numList), end=",")
    print("共%d個" % len(numList), end=",")
    print("共比較了%d次" % findTimes)


answer5()


class answer6:
    """
    練習叠代器
    """

    def __init__(self):
        """
        構造函數
        """
        self.sumCount = 0
        self.findTimes = 0
        self.startNum = 102
        self.endNum = 2000
        print("輸出六", end=":")

    def __iter__(self):
        """
        叠代器
        :return:
        """
        return self

    def __next__(self):
        """
        叠代器next
        :return:
        """
        if self.startNum > self.endNum:
            raise StopIteration
        for num in (self.startNum - 1, self.startNum + 1):
            sqrtNum = int(math.sqrt(num))
            for i in range(5, sqrtNum + 1, 6):
                self.findTimes += 1
                if num % i == 0 or num % (i + 2) == 0:
                    break
            else:
                print(num, end=",")
                self.sumCount += 1
        self.startNum += 6


answer = answer6()
for i in answer:
    pass
print("共%d個" % answer.sumCount, end=",")
print("共比較了%d次" % answer.findTimes)


def answer7():
    """
    練習yield生成器,註意和answer6區域
    """
    print("輸出七", end=":")
    startNum = 102
    sumCount = 0
    findTimes = 0
    while startNum < 2000:
        for num in (startNum - 1, startNum + 1):
            sqrtNum = int(math.sqrt(num))
            for i in range(5, sqrtNum + 1, 6):
                findTimes += 1
                if num % i == 0 or num % (i + 2) == 0:
                    break
            else:
                sumCount += 1
                print(num, end=",")
                yield num
        startNum += 6
    print("共%d個" % sumCount, end=",")
    print("共比較了%d次" % findTimes)


for i in answer7():
    pass


def answer8():
    """
    練習數組生成器表達式
    參考:http://blog.csdn.net/u014745194/article/details/70176117
    :return:
    """
    print("輸出八", end=":")
    numList = list(filter(lambda x: x not in set([i for i in range(101, 200) for j in range(2, i - 1) if not i % j]),
                          range(101, 200)))
    print(numList, end=",")
    print("共%d個" % len(numList))


answer8()

  

python學習——練習題(12)