此代码用于打印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;
答案 0 :(得分: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#
虚伪?哎呀!
此解决方案具有相同的低效率which @TYH points out in the PL/SQL solution。这就是它需要distinct
的原因。可能这可以通过递归CTE进行优化(仅适用于11gR2)。
答案 1 :(得分:1)
这是一个“它如何运作”的答案。
外部循环处理数字1 - 30。
内循环执行实际的非素数处理。它真的只在i = 4
之后才开始(因为1,2,3是素数)。对于大多数非素数,循环将在k <= 3
之后完成,并且将打印出i
。
对于素数,它将循环遍历所有小于素数的数字。就像我们在i = 23
上一样,内循环将通过2,3,4 ... 22并完成循环而不打印任何东西。
这是我不喜欢的部分。如果你将数字分解(特别是因为我们只处理1 - 30),它们可以被2或3或另一个Prime数整除。这是愚蠢的部分。回到我们的i = 23
示例。我们将处理mod(23,3)和mod(23,9)以及mod(23,18)。当然,如果3产生的余数超过9,那么18也将产生余数(每个后续数字的因子为3)。
答案 2 :(得分:0)
该代码通过测试所有潜在的候选者来工作,这意味着所有正整数大于1且更少受到审查的数量。如果候选人在没有余数的情况下划分测试的数字,则该数字是复合的并且将被打印。对帽子编号的任何进一步测试都会被跳过。