夜猫猫 发表于 2012-11-3 14:17:36

又回初中时代了。。。

shenrenba 发表于 2012-11-3 14:33:54

来看看高效率的我的计算就不发了太耗时间

nmgwddj 发表于 2012-11-3 20:02:39

学习思路,我也只能一步一步的算,效率问题考虑不到。。。

xms77 发表于 2012-11-3 21:41:11

回复 17# happytc
强淫呐~~,学习一下!是否能看懂代码。

cheng8457 发表于 2012-11-5 14:47:57

學習了!!!!{:face (356):}

bfgxp 发表于 2012-11-5 19:53:10

进来看看。以前刚学习qb里,也玩过最基础的。
看来这里高手多。

runsnake 发表于 2012-11-6 18:42:54

本帖最后由 runsnake 于 2012-11-6 18:48 编辑

回复 17# happytc


    回复看看代码


天,这个代码效率也太高了,不可思议的地高
可惜,我一点都看不懂,那位高人讲讲这是怎么实现的,原理是什么?

最好是一行行在注释,我真的一点都没有看懂写的啥?

edisonx 发表于 2012-11-7 01:17:55

RE: 出题:枚举N以内的质数(素数)

本帖最后由 edisonx 于 2012-11-7 03:56 编辑

回复 17# happytc

happytc 兄太強了,
請教 sBytecode其實是事先算好的 binary table,
然後呼叫 API 去做顯示動作,請問對嗎?


------------------
To All

初版寫得較慢,100 萬 4 秒才跑得完。
另一版的 code (本文下面會附) ,效率目前應僅次於 17F happytc 兄 ,
附上目前測時,N=100萬,不計輸出時間,執行時間在 5 secs 內之整理。


出题:枚举N以内的质数(素数)

Prime-3F-netegg.au3    3331.174729
Prime-16F-3mile.au3    2988.0624158
Prime-17F-happytc.au3   52.9091249
Prime-39F-edisonx-1.au3    3948.878543
Prime-39F-edisonx-2.au3    1750.200700


為避免測時爭議,附上附件。另若覺得不妥,請告知,小弟將刪除。



小弟初版使用的是線性篩法。#include<array.au3>
#include <timers.au3>
const$n = 1000000
; -------------
$cnt = 0.5 * $n
Global $Prime[$cnt] =

$begin = _Timer_Init()
$cnt = LinearEratosthenes($n)
$td = _Timer_Diff($begin)
MsgBox(0, "", StringFormat("Find Prime Table Td = %lf msecs, cnt = %d", $td, $cnt))
; _ArrayDisplay($Prime)

; ------------------------------------------
; byEdisonX
Func LinearEratosthenes($n)
      Local $i, $j, $c=2, $gap
      Local $p[$n+1]
           ; Local $end =Int(Ceiling( Sqrt($n) ))

      $Prime = 2
      $Prime = 3

      $p = 1
      $p = 1
      $p = 1

      $gap = 2
      $i = 5
      While $i < $n
                If Not $p[$i] Then
                        $Prime[$c] = $i
                        $c+=1
                EndIf
                For $j =0 To $c
                        $tmp= $i * $Prime[$j]
                        If $tmp> $n Then ExitLoop
                        $p[$tmp ] = 1
                Next
                $i += $gap
                $gap = 6 - $gap
      WEnd
      Return $c
EndFunc
我要講的是,由於題目要求的是「小於 N 的所有質數」,
目前已有現有效率高的演算法可滿足這需求:埃拉托斯特尼篩法。

然後第一份程式碼主要比的不是速度,
而是另一種概念上 present,寫的是埃拉托斯特尼線性篩法
也就是每次找到的質數都加到一個質數表中,加速刪除速度,所以上面程式碼一開始就宣告了很大的陣列出來。
( 不過測試出來是沒比較快就是了 )

-------------------

另外 埃拉托斯特尼篩法還可配合 2n/ 6n/ sqrt 法則,刪除時從 i*i開始刪 , step 2i 便可 (這前面回覆好像已有提到了)
若還可使用位元運算,會增加 cache hit,速度會更快 ( 但這受限於 AU 語言特性,大概辦不太到吧),
以下演示幾個重點 (1) 只查 6n+-1(2) 只查到 sqrt(n)(3) 刪除時從 i*i 開始 ,step 2i
#include<array.au3>
#include <timers.au3>
const$n = 1000000
; -------------

$begin = _Timer_Init()
$Prime = Eratosthenes6n($n)
$td = _Timer_Diff($begin)
MsgBox(0, "", StringFormat("Find Prime Table Td = %lf msecs", $td))
_ArrayDisplay($Prime)

; ------------------------------------------
; byEdisonX
Func Eratosthenes6n($n)
      Local $i, $j, $c=2, $gap, $i2
      Local $p[$n+1]
           Local $end =Int(Ceiling( Sqrt($n) ))

           $gap = 2
      $i = 5
           While $i < $end
                   If Not $p[$i] Then
                           $i2 = $i+$i
                           For $j = $i*$i To $n Step $i2
                                   $p[$j] = 1
                           Next
                   EndIf
                   $i+= $gap
                   $gap = 6 - $gap
           WEnd

        $i = 5
        $gap = 2
        $ret = "2 3 "
        While $i < $n
                IfNot $p[$i] Then $ret &=$i & " "
                $i += $gap
                $gap = 6 - $gap
        WEnd
        $ret = StringSplit(StringTrimRight($ret, 1), " ")
        return $ret
EndFunc
小弟學淺,其他的就不嘴炮了。
關於質數篩法,有興趣可參考小弟部落格 深入質數 (2/4) - 埃拉托斯特尼篩法
當時做的是 10 億 (用 C 語言實作就是了),約 10 秒完成 ( 其實算是很慢的速度 )。

最後想請教各位,包 code 怎麼 highlight ? 謝謝。

happytc 发表于 2012-11-7 21:44:18

回复 39# edisonx

請教 sBytecode其實是事先算好的 binary table,
然後呼叫 API 去做顯示動作,請問對嗎?

肯定不是table了,若算十亿,光存这些素数就得差不多500M才行,你看上面的变量sBytecode的值才多少字节?

其实我的代码里已经用到了你做的第二种‘埃拉托斯特尼篩法’,不过在这基础上用汇编先得到sBytecode后套上字节码筛选。又事先申请一大块内存待用,所以速度才快。


若還可使用位元運算,會增加 cache hit,速度會更快 ( 但這受限於 AU 語言特性,大概辦不太到吧),
不大明白你说的术语,可能是两岸所用术语不一样,但我猜十有八九我用的就是上面你所说的!

edisonx 发表于 2012-11-7 22:04:15

回复 40# happytc


    謝謝 happytc 您的細心解說。

   另所謂的位元運算,指的是 bitwise hacker,抱歉我沒注意到兩岸的名詞有些差異,下次會注意,附上英文,最後謝謝您不吝分享這麼神奇的程式碼,受益良多 :)

jevonleen 发表于 2013-3-9 06:56:05

向各位前辈学习

mbdnmt 发表于 2013-3-9 11:01:36

用了3楼的脚本,把值调到10000000,跑了好多分钟,耗内存到284M,算出有664579个质数,最大的质数是9999991

数学上是有最大质数这一说的吧?

1361739590 发表于 2013-3-9 13:51:30

来看看 学习学习

henry10423 发表于 2013-3-11 17:48:52

酷!好!棒!

cvwyg 发表于 2013-3-15 19:40:59

收藏了。谢谢楼主分享
页: 1 2 [3] 4 5
查看完整版本: 出题:枚举N以内的质数(素数)[已解决]