Resposta do wiki da comunidade :
Você pode se decepcionar com os resultados no SQL Server em comparação com o PostgreSQL (que é capaz de lidar com números muito grandes, como 30000! Sem perda de precisão).
Em SQL Server 33!é tão alto quanto você pode ir com precisão exata enquanto 170!é tão alto quanto você pode ir a todos ( 171!é1.24E309 o que ultrapassa os limites da float).
Então você pode pré-calculá-los e armazená-los em uma tabela com valores 0 ... 170. Isso cabe em uma única página de dados se a compactação for usada.
CREATE TABLE dbo.Factorials
(
N TINYINT PRIMARY KEY WITH (DATA_COMPRESSION = ROW),
FactorialExact NUMERIC(38, 0) NULL,
FactorialApprox FLOAT NOT NULL
);
WITH R(N, FactorialExact, FactorialApprox)
AS (SELECT 0,
CAST(1 AS NUMERIC(38, 0)),
1E0
UNION ALL
SELECT R.N + 1,
CASE WHEN R.N < 33 THEN ( R.N + 1 ) * R.FactorialExact END,
CASE WHEN R.N < 170 THEN ( R.N + 1 ) * R.FactorialApprox END
FROM R
WHERE R.N < 170)
INSERT INTO dbo.Factorials
(N,
FactorialExact,
FactorialApprox)
SELECT N,
FactorialExact,
FactorialApprox
FROM R
OPTION (MAXRECURSION 170);
Alternativamente, o seguinte irá dar resultados precisos para @N até 10 - e aproximado para 11+ (seria mais preciso se as várias funções / constantes ( PI(), EXP(), POWER()) trabalhou com DECIMALtipos, mas eles trabalham com FLOATapenas):
DECLARE @N integer = 10;
SELECT
CONVERT
(
DECIMAL(38,0),
SQRT(2 * PI() * @N) *
POWER(@N/EXP(1), @N) *
EXP(1.0/12.0/@N + 1.0/360.0/POWER(@N, 3))
);