web-dev-qa-db-ja.com

SQL素数関数

番号Xがあり、SQL-Serverを使用してIsPrime(X) = true/falseと言いたい場合、最善のアプローチは何ですか?

素数のテーブルをインポートするだけですか、それとも小さい素数に対してかなり効率的なアルゴリズムがありますか?

注:私は約よりも大きい数には興味がありません。千万。

以下を使用することになりました:

CREATE FUNCTION [dbo].[isPrime]
(
    @number INT
)
RETURNS VARCHAR(10)

BEGIN


    DECLARE @retVal VARCHAR(10) = 'TRUE';

    DECLARE @x INT = 1;
    DECLARE @y INT = 0;

    WHILE (@x <= @number )
    BEGIN

            IF (( @number % @x) = 0 )
            BEGIN
                SET @y = @y + 1;
            END

            IF (@y > 2 )
            BEGIN
                SET @retVal = 'FALSE'
                BREAK
            END

            SET @x = @x + 1

    END

    RETURN @retVal
END
9
whytheq

これは多くの人に起こっていないのではないかと思いますが、チェックする必要があるのは、新しい数がそれぞれ前の素数で割り切れるかどうかだけです...

create table prime (primeno bigint)
declare @counter bigint
set @counter = 2
while @counter < 1000000
begin
if not exists(select top 1 primeno from prime where @counter % primeno = 0 )

-上記で、ANDプライム<@counter/2などを追加すると、チェックのオーバーヘッドがさらに削減されます。

insert into prime select @counter
set @counter = @counter + 1
end
select * from prime order by 1

怠惰なコーディングですが、私の隣のような遅い仮想PCでも、数分で最大100万個のすべてを手に入れることができます。何かを見落としていない限り、78,498個にします(1を数えない場合)。

6
Simon UK
CREATE  proc prime  
@no int  
as   
declare @counter int  
set @counter =2  
begin  
while(@counter)<@no  
 begin  
 if(@no%@counter=0)  
  begin  
  select 'Not prime'  
  return  
  end  
  set @counter=@counter+1  
 end  
 select 'prime'  
 return  
end  

--exec prime 10  
4
user3545257

シーケンス生成 に基づいて、関数や反復プロセス(while)なしで素数を生成する興味深い方法があります。基本的には2 .. @maxシーケンスが生成され、シーケンス内に他にないすべての番号をcurrent%other = 0

declare @max INT = 10000

;WITH all_numbers(n) AS
(
    SELECT 2
    UNION ALL
    SELECT n+1 FROM all_numbers WHERE n < @max
)
select all1.n as prime
from all_numbers all1
where not exists (select 1 from all_numbers all2 where all2.n < all1.n AND all1.n % all2.n = 0)
order by all1.n
-- beware, 0 means no limit. Otherwise 32767 can be the max specified
OPTION (MAXRECURSION 0)

このソリューションの主な欠点はパフォーマンスです(たとえば、20000まですべての素数を生成するのに約17秒かかりました)。

3
Alexei

これはうまく機能する簡単なスクリプトです。必要に応じて@numを調整します。

declare @nonprimes table (number int) 
declare @primes table (number int) 
declare @num int = 2
declare @divisor int  = 1
while @num<10000
begin

while @divisor>1
begin
if @num % @divisor=0 
insert @nonprimes
select @num
if @@rowcount>0 goto A

set @divisor=@divisor-1

end
insert @primes
select @num
A: set @num=@num+1 
set @divisor=@num-1

end

select sum(number) from @primes
0
Daniel Marcus