Функция простого числа SQL

Если у меня есть число X и я хочу сказать IsPrime(X) = true/false использование sql-server каков наилучший подход?

Я просто импортирую таблицу простых чисел или есть алгоритм, который достаточно эффективен для меньших простых чисел?

Примечание: меня не интересуют цифры больше, чем прибл. 10-миллионный.

в конечном итоге с помощью следующего:

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

6 ответов


вы могли бы, как вы сказали, иметь стол, который хранит все простые числа до 10 млн.. Тогда было бы тривиально посмотреть, является ли число простым или нет. Вопрос в том, какой метод будет быстрее. Я подозреваю, что таблица будет намного быстрее (я не тестировал это утверждение).

Решение Таблицы Prime

SQL Function Solutions

решение 0

вот одно решение через поиск простых чисел с помощью функции Transact-SQL:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
–- =============================================
–- Author:        Nicolas Verhaeghe
–- Create date: 12/14/2008
–- Description:   Determines if a given integer is a prime
/*

      SELECT dbo.IsPrime(1)

      SELECT dbo.IsPrime(9)

      SELECT dbo.IsPrime(7867)

*/
–- =============================================
CREATE FUNCTION [dbo].[isPrime]
(
      @NumberToTest int
)
RETURNS bit
AS
BEGIN
      -– Declare the return variable here
      DECLARE @IsPrime bit,
                  @Divider int

      –- To speed things up, we will only attempt dividing by odd numbers

      –- We first take care of all evens, except 2
      IF (@NumberToTest % 2 = 0 AND @NumberToTest > 2)
            SET @IsPrime = 0
      ELSE
            SET @IsPrime = 1 –- By default, declare the number a prime

      –- We then use a loop to attempt to disprove the number is a prime

      SET @Divider = 3 -– Start with the first odd superior to 1

      –- We loop up through the odds until the square root of the number to test
      –- or until we disprove the number is a prime
      WHILE (@Divider <= floor(sqrt(@NumberToTest))) AND (@IsPrime = 1)
      BEGIN

            –- Simply use a modulo
            IF @NumberToTest % @Divider = 0
                  SET @IsPrime = 0
            –- We only consider odds, therefore the step is 2
            SET @Divider = @Divider + 2
      END  

      –- Return the result of the function
      RETURN @IsPrime

END
Решение 1

здесь другое решение через как найти, является ли простым или не простым с одним оператором select? в других комментариях также есть дополнительная информация.

CREATE FUNCTION isPrime
(
    @number INT
)
RETURNS VARCHAR(10)
BEGIN
    DECLARE @prime_or_notPrime INT
    DECLARE @counter INT
    DECLARE @retVal VARCHAR(10)
    SET @retVal = 'FALSE'

    SET @prime_or_notPrime = 1
    SET @counter = 2

    WHILE (@counter <= @number/2 )
    BEGIN

        IF (( @number % @counter) = 0 )
        BEGIN
            set @prime_or_notPrime = 0
            BREAK
        END

        IF (@prime_or_notPrime = 1 )
        BEGIN
            SET @retVal = 'TRUE'
        END

        SET @counter = @counter + 1
    END
    return @retVal
END

Я подозреваю, что это не пришло в голову многим людям, но все, что вам нужно проверить, является ли каждое новое число делится на предыдущие простые числа...

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 )

-- выше, добавление и prime

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

ленивое кодирование, но даже на медленном виртуальном ПК, таком как рядом со мной, у вас будет все до миллиона за несколько минут. Я делаю это 78,498 из них (если вы не считаете 1), Если я не пропустил что-то.


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  

есть интересный способ генерации простых чисел без какой-либо итерационный процесс (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)

основным недостатком этого решения является производительность (например, потребовалось около 17s для генерации всех простых чисел до 20000).


вот простой скрипт, который работает прекрасно. Отрегулируйте @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

Create PROC prime @num int , @flag int OUTPUT
AS
   Declare @i=50
   set

   while (@i<@num)
Begin
     if @i%@num=0
     break
set
     @i=@i+1
  End
  if @i=@num
 set
    @glag=1
else
   set
      @flag=2


Declare @ans int
Exec prime 50,@flag=@ans OUTPUT
if @ans=1
print 'The number is prime'
else
print 'The number is composite'