Как найти факториал для данного числа без использования символа * в запросе T-SQL? - PullRequest
0 голосов
/ 28 апреля 2018

Я получил факториальное значение с помощью символа *:

declare @given_number int=5;
declare @fact int=1;

while(@given_number > 1)
begin
    set @fact = @fact * @given_number;
    set @given_number = @given_number - 1;
end

select @fact as 'Factorial is '

Но теперь я хочу получить то же факториальное значение без использования * символа

Можете ли вы помочь мне, задав правильный вопрос?

Ответы [ 3 ]

0 голосов
/ 29 апреля 2018

Я бы использовал простую арифметику:

set @fact = exp(log(@fact) + log(@given_number));

На самом деле, вы можете просто добавить журналы в цикл, но зачем использовать цикл while?

with f as (
      select @given_number as n
      union all
      select n -1
      from f
      where n > 1
     )
select exp(sum(log(f.n)))
from f;

Это имеет приятную особенность - он ограничен диапазоном значений с плавающей запятой, а не целыми числами.

0 голосов
/ 29 апреля 2018

Запрос на поиск факториала без использования оператора * в T-SQL

declare @Given_number int=7;
declare @y int=0;
declare @z int=0;
declare @a int=@given_number;
declare @b int=@given_number;
declare @i int=@a;
while(@i>1)
begin
declare @j int=1;
while(@j<@i)
begin
set @z=@b+@y;
set @y=@z;
set @j=@j+1;
end
set @b=@z;
set @y=0;
set @i=@i-1;
end 
select @z as 'Factorial'
0 голосов
/ 28 апреля 2018

Да, это очень легко сделать с CHOOSE:

declare @given_number int=5;

SELECT 
  @given_number AS given_number,
  CHOOSE(@given_number
    ,1
    ,2
    ,6
    ,24
    ,120
    ,720
    ,5040
    ,40320
    ,362880
    ,3628800
    ,39916800
    ,479001600
    ,6227020800
    ,87178291200
    ,1307674368000
    ,20922789888000
    ,355687428096000
    ,6402373705728000
    ,121645100408832000
    ,2432902008176640000) AS factorial;

Демоверсия DBFiddle


РЕДАКТИРОВАТЬ (забавная часть):

Но примете ли вы вызов Мартина Смита, исключая букву S?

Сегодня я вспоминаю, что CASE/IIF может быть вложено только 10 раз:)

declare @given_number int=5;

PRINT CONCAT('For ' ,@given_number, ' factorial = ',
IIF(@given_number=1,1
,IIF(@given_number=2,2
,IIF(@given_number=3,6
,IIF(@given_number=4,24
,IIF(@given_number=5,120
,IIF(@given_number=6,720
,IIF(@given_number=7,5040
,IIF(@given_number=8,40320
,IIF(@given_number=9,362880
,IIF(@given_number=10,3628800, -1)))))))))));

DBFiddle Demo2

EDIT2:

Один из способов обойти ограничение IIF - использовать оригинальный запрос с динамическим SQL + exchange S с CHAR(83):

declare @t NVARCHAR(MAX) = 'declare @given_number int=5;' +  CHAR(83) + 'ELECT   given_number = @given_number,   factorial = CHOO'+  CHAR(83) +'E(@given_number    ,1    ,2    ,6    ,24    ,120    ,720    ,5040    ,40320    ,362880    ,3628800    ,39916800    ,479001600    ,6227020800    ,87178291200    ,1307674368000    ,20922789888000    ,355687428096000    ,6402373705728000    ,121645100408832000    ,2432902008176640000);';

EXEC(@t);

DBFiddle Demo3

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...