[英]How to print prime numbers within given range | Oracle 19c |
I have been trying to write a logic to print all prime numbers .我一直在尝试编写一个逻辑来打印所有素数。
And it works as expected till range of 1
to 100
.它可以按预期工作,直到范围为
1
到100
。
But when I increase the range it dose not work from 1
to 500
但是当我增加范围时,它从
1
到500
不起作用
Can some explain in details what is wrong in my below code and how it can be improved.有人可以详细解释我下面的代码有什么问题以及如何改进它。
Any easy or different way to print prime numbers will be much appreciated任何简单或不同的打印素数的方法都将不胜感激
Code:代码:
SELECT
result
FROM
(
SELECT
CASE
WHEN ROWNUM = 2 THEN
ROWNUM
WHEN ROWNUM = 3 THEN
ROWNUM
WHEN ROWNUM = 5 THEN
ROWNUM
END AS result
FROM
dual
CONNECT BY
ROWNUM <= 5
)
WHERE
result IS NOT NULL
UNION ALL
SELECT
result
FROM
(
SELECT
decr1 AS result
FROM
(
SELECT
rn AS decr1
FROM
(
SELECT
ROWNUM AS rn
FROM
dual
CONNECT BY
ROWNUM < 1000
)
)
WHERE
decr1 > 5
MINUS
SELECT
decr AS result
FROM
(
SELECT
t.rn AS decr
FROM
(
SELECT
ROWNUM AS rn
FROM
dual
CONNECT BY
ROWNUM < 1000
) t
WHERE
rn >= 6
)
WHERE
mod(decr, 2) = 0
OR mod(decr, 3) = 0
OR mod(decr, 4) = 0
OR mod(decr, 5) = 0
OR mod(decr, 6) = 0
OR mod(decr, 7) = 0
OR mod(decr, 8) = 0
OR mod(decr, 9) = 0
OR mod(decr, 10) = 0
);
My output for range of 1
to 100
我的 output 范围为
1
到100
A positive integer is prime if it is strictly greater than 1, and if it is not divisible by any positive integers besides 1 and the number itself.正数 integer 如果严格大于 1,并且不能被除 1 和数字本身之外的任何正整数整除,则它是素数。 To check for primality, it is enough to know if the number is divisible by a number between 2 and trunc(sqrt(that_number)).
要检查素数,知道该数字是否可以被 2 和 trunc(sqrt(that_number)) 之间的数字整除就足够了。 In code:
在代码中:
with
user_input (n) as (
select :n -- user input goes here
from dual
)
, candidates (p) as (
select level
from user_input
where level > 1
connect by level <= n
)
, prep (f) as (
select level
from dual
where level > 1
connect by level <= trunc(sqrt(:n))
)
select p as prime
from candidates
where not exists (
select f
from prep
where f <= trunc(sqrt(p))
and
mod(p, f) = 0
)
;
The input (at the top of the query, in the with
clause) is a bind variable, you can set it to 100 or whatever you need.输入(在查询的顶部,在
with
子句中)是一个绑定变量,您可以将其设置为 100 或任何您需要的值。
NOTE: This will be quite slow if you need all the primes up to 100,000 for example (it takes 2.3 seconds on my machine).注意:例如,如果您需要所有素数高达 100,000,这将非常慢(在我的机器上需要 2.3 秒)。 Don't even try up to 1 million or more.
甚至不要尝试达到 100 万或更多。 For those, you need a better algorithm.
对于那些,你需要一个更好的算法。 We all learned the Erathostenes' sieve algorithm in primary school;
我们在小学都学过 Erathostenes 的筛分算法; that is trivial to code in a procedural language (like PL/SQL), not so easy in a declarative language (like SQL - proving that "declarative" is just a marketing word, and perhaps an ideal, but not a reality).
这对于用过程语言(如 PL/SQL)编写代码来说是微不足道的,但在声明性语言(如 SQL - 证明“声明性”只是一个营销词,也许是一个理想,但不是现实)中并不容易。 For a pretty long discussion see https://community.oracle.com/tech/developers/discussion/3931268/sql-puzzle-prime-numbers/p1 which was rendered hard to read by Oracle's change of forum platform provider a few years back.
对于相当长的讨论,请参阅https://community.oracle.com/tech/developers/discussion/3931268/sql-puzzle-prime-numbers/p1几年前 Oracle 更改论坛平台提供商时很难阅读.
select num prime_number
from (select level num from dual connect by level <= 500 ),
(select level denom from dual connect by level <= 500 )
where denom<=num
group by num
having count(case num/denom when trunc(num/denom) then 'Y' end) = 2
order by num
Using Oracle's connect, we can generate our set of numerators and denominators.使用 Oracle 的连接,我们可以生成我们的一组分子和分母。 Then we can filter any denominators greater than the numerator (no point in dividing 2 by 3, etc).
然后我们可以过滤任何大于分子的分母(没有必要将 2 除以 3 等)。 Finally, the having clause will return the prime numbers.
最后,having 子句将返回素数。
Fiddle The first query in the fiddle kind of shows what is going on, the second one is gives you your primes.小提琴 小提琴中的第一个查询显示正在发生的事情,第二个查询是给你你的素数。
You've thrown out processing efficiency when you decided to do this in SQL, so you might as well go for something that is clear.当您决定在 SQL 中执行此操作时,您已经放弃了处理效率,因此您不妨 go 来做一些明确的事情。 Here is a SQL that is pretty much straight along the lines of the definition of a prime number:
这是一个 SQL ,它与质数的定义非常相似:
with nat as (SELECT rownum n FROM DUAL CONNECT BY ROWNUM <= 100 )
SELECT n -- give me any number...
from nat n1 -- ... from the set of natural numbers ...
where not exists ( SELECT n FROM nat n2 where mod(n1.n,n2.n)=0 AND n2.n between 2 and n1.n-1) -- ... that cannot be evenly divided by a smaller natural number
and n > 1 -- ... and 1 is not prime
Adjust the CONNECT by value if you want more or less values如果您想要更多或更少的值,请按值调整 CONNECT
select a output
from (select level a from dual connect by level <= 500),
(select level b from dual connect by level <= 500)
where b<=a
group by a
having count(case a/b when trunc(a/b) then 'Y' end) = 2
order by a;
You can use use a row-generator to generate all the values and then use CROSS JOIN LATERAL
to check if each value is prime:您可以使用行生成器生成所有值,然后使用
CROSS JOIN LATERAL
检查每个值是否为素数:
SELECT prime
FROM (
SELECT LEVEL + 1 AS prime
FROM DUAL
CONNECT BY LEVEL < 100
) p
CROSS JOIN LATERAL (
SELECT 1
FROM DUAL
WHERE MOD(prime, level) = 0
CONNECT BY LEVEL * LEVEL <= prime
HAVING COUNT(*) = 1
)
Which outputs:哪个输出:
PRIME 主要
2 2
3 3
5 5
7 7
11 11
13 13
17 17
19 19
23 23
29 29
31 31
37 37
41 41
43 43
47 47
53 53
59 59
61 61
67 67
71 71
73 73
79 79
83 83
89 89
97 97
Hooray finally !!!终于万岁了!!!
I was able to solve the question by taking references from all @authors我能够通过参考所有@authors 来解决这个问题
My sincere thank you to all the author who as come up with different solution我真诚地感谢所有提出不同解决方案的作者
I got few ideas from your logic which help me to write a below query我从你的逻辑中得到了一些帮助我编写以下查询的想法
My code:我的代码:
with input(val) as
(
SELECT
:val
FROM
dual
)
,
auto_generate_number_sequence as
(
SELECT
numbr
FROM
(
SELECT
6 * level - 1 AS numbr
FROM
dual
CONNECT BY
level < :val
UNION
SELECT
6 * level + 1 AS numbr
FROM
dual
CONNECT BY
level < :val
)
WHERE
numbr <= :val
) ,
generate_sqrt_of_input as
(
select
level as sqrtnum
from dual where level > 1 connect by level <=sqrt(:val)
)
, get_numbers_remainder_zero as
(
SELECT
numbr,
mod(numbr, sqrtnum) AS md
FROM
auto_generate_number_sequence
CROSS JOIN generate_sqrt_of_input
WHERE
sqrtnum < (numbr/2)
AND mod(numbr, sqrtnum) = 0
ORDER BY
numbr,
mod(numbr, sqrtnum)
)
SELECT
level numbr
FROM
dual where level > 1
CONNECT BY
level <=3
UNION
SELECT
numbr
FROM
auto_generate_number_sequence
MINUS
SELECT
numbr
FROM
get_numbers_remainder_zero;
Please feel free to correct me If any issue with my above query如果我的上述查询有任何问题,请随时纠正我
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.