-3

此代码用于打印 1 到 30 之间的非素数。它是如何工作的,错误在哪里。

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;
4

3 回答 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#

虚伪?哎呀!


该解决方案具有与@TYH 在 PL/SQL 解决方案中指出的相同的低效率。这就是为什么它需要distinct. 可能这可以通过递归 CTE 进行优化(仅在 11gR2 中可用)。

于 2013-04-23T14:39:36.107 回答
1

这是一个“它是如何工作的”的答案。

外部循环处理数字 1 - 30。

内部循环执行实际的非素数处理。它真的只有在之后才开始i = 4(因为 1,2,3 是素数)。对于大多数非质数,循环将在 while 之后完成,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 的数)。

于 2013-04-23T14:44:26.957 回答
0

该代码通过测试所有潜在候选人来工作,这意味着所有大于 1 且小于被审查数字的正整数。如果候选人将测试的数字除以没有余数,则该数字是复合数字并将被打印。跳过任何关于帽子号码的进一步测试。

于 2013-04-23T14:43:58.213 回答