2013-04-23 35 views
-3

此代碼旨在打印1到30之間的非素數。它如何工作以及錯誤在哪裏。如何打印非素數? PL/SQL

BEGIN 
    <<outer>> 
    FOR i in 1..30 
     <<inner>> 
     for k in 2..i-1 loop 
      if (mod(i, k) = 0) THEN 
       DBMS_OUTPUT.PUT_LINE(i); 
       exit inner when (mod(i, k)= 0); 
      end if; 
     end loop inner 
    end loop outer 
end; 
+1

顯然它不起作用。當'i = 1'時,'2..i-1'中的k解析爲'2..0'中的k。還有其他一些錯誤,但這代碼高爾夫,所以它是關閉主題。 – APC 2013-04-23 14:22:44

+2

@APC:令人驚訝的是,似乎確實有效。一旦你修復了語法錯誤,輸出是正確的。 the5strace:請更正語法(仔細查看你的兩個「for」行,你會看到不同)。然後記住';'不只是裝飾。有些地方需要他們。 – Mat 2013-04-23 14:28:31

+0

@APC'i = 1'的情況是有效的,因爲plsql要求第一個邊界低於第二個邊界以進入循環。反轉迭代順序需要修改器'REVERSE',如'FOR k IN REVERSE LO..HI LOOP ... END LOOP'。 – collapsar 2013-04-23 14:39:53

回答

1

這是「它是如何工作」的答案。

外環手柄經歷數字1 - 30.

內環執行實際的非素數的處理。它只有在i = 4之後纔會開始(因爲1,2,3是首要的)。對於大多數非素數,循環將在k <= 3之後完成,並將打印出i。 對於素數,它將遍歷所有小於素數的數字。就像我們在i = 23內循環將要經過2,3,4 ... 22並完成循環而不打印任何東西。

這是我不喜歡的部分。如果你將數字分解(特別是因爲我們只處理1 - 30),它們可以被2或3或另一個素數整除。這是愚蠢的部分。回到我們的i = 23的例子。我們將要處理mod(23,3)和mod(23,9)和mod(23,18)。當然,如果3產生的餘數不超過9,那麼18也會產生一個餘數(每個隨後的數字都會產生一個3的因子)。

5

有一個休息時間,所以這裏是一個純粹的SQL實現。

with data as (select level as n# from dual 
       connect by level <= 30) 
select distinct d1.n# 
from data d1 cross join data d2 
where d1.n# > d2.n# 
and d2.n# != 1 
and mod(d1.n#, d2.n#) = 0 
order by d1.n# 

Hypocrisy?哎呀!


該解決方案具有相同的低效率which @TYH points out in the PL/SQL solution。這就是爲什麼它需要distinct。可能這可以通過遞歸CTE進行優化(僅適用於11gR2)。

+0

虛僞?爲什麼在PL/SQL中可以使用SQL來完成它們呢? – 2013-04-23 14:50:22

+0

@ Colin'tHart - 我同意。但我稱之爲虛僞,因爲我已經提出這是Code Golf而不是一個恰當的問題。 – APC 2013-04-23 14:55:57

+1

愚蠢的一致性是小心靈的大地精。假裝很好,哦,偉大的思想家! :-) – 2013-04-23 15:44:30

0

該代碼的工作原理是通過測試所有潛在的候選人,意味着所有大於1的正整數以及在詳細審查中的數量。如果候選人將剩餘的測試號碼分開,則該號碼爲合成號碼並將被打印。任何進一步的帽子號碼測試都會被跳過。