Réponse du wiki communautaire :
Vous pouvez être déçu des résultats dans SQL Server par rapport à PostgreSQL (qui est capable de traiter de très grands nombres tels que 30000! Sans perte de précision).
Dans SQL Server 33!
est aussi haut que vous pouvez aller avec une précision exacte , tout 170!
est aussi haut que vous pouvez aller du tout ( 171!
est1.24E309
ce qui dépasse les limites de float
).
Vous pouvez donc simplement les précalculer et les stocker dans une table avec des valeurs 0 ... 170
. Cela tient sur une seule page de données si la compression est utilisée.
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);
Sinon, ce qui suit donnera des résultats précis pour @N jusqu'à 10 - et approximative 11+ (il serait plus exact si les différentes fonctions / constantes ( PI()
, EXP()
, POWER()
) ont travaillé avec les DECIMAL
types , mais ils travaillent avec FLOAT
seulement):
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))
);