Ответ сообщества вики :
Вы можете быть разочарованы результатами в SQL Server по сравнению с PostgreSQL (который может работать с очень большими числами, такими как 30000! Без потери точности).
Уровень SQL Server 33!
настолько высок, насколько вы можете идти с точной точностью, и в то же время 170!
настолько высок, насколько вы можете идти вообще ( 171!
это1.24E309
превышает пределы float
).
Таким образом, вы можете просто пересчитать их и сохранить их в таблице со значениями 0 ... 170
. Это помещается на одной странице данных, если используется сжатие.
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);
Кроме того , следующий будет давать точные результаты для @N до 10 - и приближенного для 11+ (это было бы более точным , если различные функции / константы ( PI()
, EXP()
, POWER()
) работали с DECIMAL
типами , но они работают с FLOAT
только):
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))
);