|
终于把这个大数搞出来。
with src as (select '73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450' xx from dual),
s as (select regexp_replace(xx,'[^0-9]','') x from src)
,d AS (SELECT ROWNUM n FROM s CONNECT BY ROWNUM<=LENGTH(x))
,t AS (
SELECT d1.n pos
,d2.n len
,d3.n pos2
,TO_NUMBER(SUBSTR(x,d1.n+d3.n-1,1)) n
FROM s,d d1, d d2, d d3
WHERE d1.n + d2.n -1 <= LENGTH(x) AND d3.n<=d2.n
AND INSTR(SUBSTR(x,d1.n,d2.n),'0')=0
)
,t2 AS (
SELECT LEVEL n, TO_NUMBER(SUBSTR(x,pos+LEVEL-1,1)) val,pos,len
FROM (SELECT pos,len
FROM (
SELECT pos,len,SUM(LN(n))
FROM t
GROUP BY pos,len
ORDER BY 3 DESC
)
WHERE ROWNUM=1
)
,s
CONNECT BY LEVEL<=len
)
,tmp AS
(SELECT *
FROM (SELECT n,col,prod,val,len,pos
FROM t2
,( SELECT ROWNUM col
-- 构造一个30 行的集合,这个集合的每一行用于存放30 位的临时计算结果
FROM DUAL
CONNECT BY ROWNUM<=30
) -- 上述两个集合做笛卡儿积,就为每个乘数n 分配了30 个col 作临时存放单元,
-- 最大可表示900 位的数字,用于存放对n 做阶乘的结果
MODEL IGNORE NAV RETURN UPDATED ROWS
DIMENSION BY (n,col) -- 用于定位到单元格的唯一标识
MEASURES (0 prod,val,len,pos ) -- prod 用于存放30 位的计算结果
RULES (
prod[any,any] order by n,col
-- MODEL 的规则指定n 从1~len,每个n 的col 从1~30 的顺序进行下列运算
=(CASE WHEN cv(n)=1 AND cv(col)=1 THEN val[1,1] -- 递归计算起点
ELSE MOD(prod[cv()-1,cv()],1E30)*val[cv(),1]
--取出在相同位置(col 相同)
--的计算结果的后30 位,乘以当前乘数val[cv(),1]
+TRUNC(prod[cv(),cv()-1]/1E30)
-- 再加上上一步乘法运算(位置col-1)的结果的进位部分
END)
)
)
WHERE n=len -- 在计算的结果中取出最后的那些单元格,用于拼接输出
)
SELECT SUBSTR(x,pos,len) str,pos,len,prod
FROM (SELECT MAX(pos) pos
,MAX(len) len
,LTRIM(REPLACE(MAX(SYS_CONNECT_BY_PATH(LPAD(MOD(prod,1E30),30,'0'),'*')),'*'),'0') as prod
FROM tmp
START WITH col=(SELECT MAX(col) FROM tmp WHERE prod>0)
CONNECT BY col = PRIOR col-1
)
,s
;
STR
----------------------------------------------------------------------------------------
POS LEN
---------- ----------
PROD
----------------------------------------------------------------------------------------
863465674813919123162824586178664583591245665294765456828489128831426
674 69
2412446685431734624320887406251212800000000
Elapsed: 00:00:08.62 |
|