2016-09-30 3 views
1

В sql2014 у меня есть таблица с 4 целыми числами (W, X, Y, Z) и bigint B. B = C (X, Z) * ​​C (WX; YZ) где C (n, k) обозначает комбинации k объектов, взятых из n объектов, то есть обычный n!/[k! (nk)!]Как рассчитать большую комбинаторную сумму в tsql

Наибольшее значение W, X, Y и Z равно 40, так что самый большой B равен 1.37847E + 11 Я могу рассчитать правильные значения с помощью Excel (используя функцию COMBIN), но я не могу сказать то же самое в SQL. Я могу создать таблицу со всеми комбинациями W, X, Y, Z, которые мне нужны, но когда я пытаюсь вычислить B для больших значений, я не знаю, как относиться к вещам типа «40!».

Я хотел бы использовать КТР с preinserted значений факториала, что-то вроде:

;WITH factorials AS(
SELECT 2 as N, 2 AS F 
UNION ALL 
SELECT 3,6 
UNION ALL... 
) 

, но я не знаю, как хранить 40! и тому подобное.

Использование .NET для заполнения таблицы не является вариантом, это должно быть сделано SQL.

Я даже подумал о том, чтобы использовать таблицу, аналогичную CTE, и хранить факториал в двух или трех столбцах, первый хранится миллиарды, второй хранится миллиарды миллиардов и т. Д. (С использованием INT), но тогда я не знаю как сделать разбиения среди чисел, хранящихся таким образом, как в (Ax10^9 + B)/(Cx10^9 + D).

Как управлять целыми числами больше, чем bigint в tsql?

+0

прямо сейчас я думаю о хорошем старом разделении среди полиномов ... и кажется почти тривиальным ... но это не так! потому что мне все еще нужно обрабатывать слишком большие цифры, возможно, –

ответ

1

Я уверен, что это не полное решение, но, возможно, это даст вам некоторые идеи о том, как начать работу. Возможно, вы могли бы сделать это хранимой процедурой и перейти в @n и @k

Использование DOUBLE, похоже, не вызывает проблем, когда я возвращаю его в BIGINT. Возможно, кто-то еще может прокомментировать очевидную опасность этого.

DECLARE @final_value DOUBLE PRECISION 
DECLARE @n INT = 40 
DECLARE @k INT = 20 

;WITH CTE AS 
(
SELECT 1 AS num,CAST(1 AS DOUBLE PRECISION) AS factorial 
UNION ALL 
SELECT num+1,CAST(factorial*(num+1)AS DOUBLE PRECISION) FROM CTE 
WHERE CTE.num < 40 
) 

SELECT * INTO #temp_numbers FROM CTE 

SET @final_value = (SELECT factorial FROM #temp_numbers WHERE num = @n)/
    (SELECT factorial FROM #temp_numbers WHERE num = @k)/
    (SELECT factorial FROM #temp_numbers WHERE num = (@[email protected])) 

PRINT CAST(@final_value AS BIGINT) 
DROP TABLE #temp_numbers 
+0

это ТОЧНО, что мне нужно. Сегодня у меня был шанс применить свой ответ к моему делу, и он работает отлично и очень быстро. Спасибо! –

Смежные вопросы