TSQL程序找到最大的素数

时间:2016-10-03 12:53:29

标签: sql-server tsql primes

我有一个整数表

number
--------
104723
104729
9998
448

目标是找到一组数字中最大的素数。我已经使用以下程序

完成了这项工作
Declare @t table(number int)
Insert into @t values(104723),(104729),(9998),(448)

Declare @maxNum INT
SELECT @maxNum = MAX(number) FROM @t

--generate a number table from 2 to the maximum number supplied
;WITH Cte AS (
    SELECT 2 AS num 
        UNION ALL
    SELECT num+1 
    FROM cte 
    WHERE num<@maxNum)

SELECT TOP(1) num AS 'Largest Prime' FROM cte
--filter by some known prime numbers (keeping the range between 2 to 19
WHERE 
    (num=2 OR num%2!=0) AND
    (num=3 OR num%3!=0) AND
    (num=5 OR num%5!=0) AND
    (num=7 OR num%7!=0) AND
    (num=11 OR num%11!=0) AND
    (num=13 OR num%13!=0) AND
    (num=17 OR num%17!=0) AND
    (num=19 OR num%19!=0) 
ORDER BY 1 DESC
OPTION (MAXRECURSION 0)


/*
Largest Prime
-------------
104729
*/

但我相信会有更好的方法。我怎样才能优化它?

2 个答案:

答案 0 :(得分:2)

我修改了一下你的查询:

DECLARE @t TABLE (number int)
INSERT INTO @t VALUES
(104723),(104729),(9998),(448)

DECLARE @maxNum int
SELECT @maxNum = MAX(number) 
FROM @t

;WITH cte AS (
    SELECT 2 AS num 
    UNION ALL
    SELECT num+1 
    FROM cte 
    WHERE num < @maxNum
)

SELECT MAX(number) as LargestPrime
FROM (
    SELECT number
    FROM @t t
    CROSS JOIN Cte c
    WHERE t.number%c.num=0 
    GROUP BY number
    HAVING COUNT(num) = 1
) as t
OPTION (MAXRECURSION 0)

这将带来@t表中最大的素数:

LargestPrime
104729

主要思想是获得最大数量,建立CTE,数字从2到最大。然后进行笛卡尔联接,这样我们就可以尝试从@t和CTE中获取每个数字的modulo。如果有数字的模数> 0超过1次 - 它们不是素数。

答案 1 :(得分:1)

略有不同的方法。

填写只有素数的表格。

然后只需将表连接到素数上并返回最大值

declare @T table (number int primary key);
insert into @T values (104723),(104729),(9998),(448);

declare @maxNum int;
set @maxNum = (select max(number) from @T);

declare @primes TABLE (n int primary key);
insert into @primes (n) values (2);

with cte as (
  SELECT 3 AS n 
  UNION ALL
  SELECT n+2 FROM cte WHERE n+2 <= @maxNum) -- Only uneven numbers lower then @maxNum
insert into @primes (n)
select n from cte
where (n%3 > 0 and n%5 > 0 and n%7 > 0) or n < 8  -- Filter a majority of the non-primes
option (MAXRECURSION 0);

-- Remove the numbers where the modulus by a lower number returns 0
-- Limiting it to the numbers lower or equal to the square root of the number.
-- The idea behind this is that even if the number has a divisor that's higher than the square root, it would mean there also exists a lower divisor.
DELETE p FROM @primes p
WHERE EXISTS (
  SELECT 1 FROM @primes AS p1
  WHERE p1.n <= CEILING(SQRT(p.n)) and (p.n%p1.n) = 0 and p.n > 8
);  


select max(t.number) as LargestPrime 
from @T t 
inner join @primes p on (t.number = p.n);

当然,如果你经常这样做,那么创建一个包含大量素数的永久表可能是值得的。