数值超过NUMBER最大表示范围的问题(五)
上一篇 / 下一篇 2006-12-19 00:00:00 / 个人分类:ORACLE
昨天同事给我出了一道简单的题——计算1阶乘到100阶乘的累加。问题似乎很简单,但是最终引出的问题并不简单。
数值超过NUMBER最大表示范围的问题(一):http://yangtingkun.itpub.net/post/468/234035
数值超过NUMBER最大表示范围的问题(二):http://yangtingkun.itpub.net/post/468/239478
数值超过NUMBER最大表示范围的问题(三):http://yangtingkun.itpub.net/post/468/240683
数值超过NUMBER最大表示范围的问题(四):http://yangtingkun.itpub.net/post/468/241044
t4Z!{5Y"f ^2E8vz8Z0
上面一篇文章给出了利用字符串的“加”和“乘”的方法,在ORACLE的PL/SQL中解决这个问题。其中,由于要保证精度,加法和乘法都对输入值进行限制,将计算范围缩短到ORACLE的NUMBER精度范围之内,通过函数的多次递归来得到最终结果。
不过,两个函数相对比较复杂,可读性较差,于是这里给出一个利用循环算法的解决方案,并利用Oracle的对象功能,将数据和方法封装起来。
SQL> CREATE OR REPLACE TYPE T_BIG_NUMBER IS OBJECT ITPUB个人空间W4I8@P n~2bMpG
2 (ITPUB个人空间zWa K:yg
3 BIG_NUMBER VARCHAR2(32767),
:vHl;g\0 4 NUMBER_LENGTH NUMBER, ITPUB个人空间7x'~1E8^
R;r
5 STATIC FUNCTION F_T_BIG_NUMBER (P_BIG_NUMBER IN VARCHAR2) RETURN T_BIG_NUMBER, ITPUB个人空间d"{fg6?"u
6 MEMBER FUNCTION ADDS(P_ADD IN T_BIG_NUMBER) RETURN T_BIG_NUMBER,
-i/e,as
k0 7 MEMBER FUNCTION MULTIS(P_MULTI IN T_BIG_NUMBER) RETURN T_BIG_NUMBER, ITPUB个人空间pM9Y_"^/C9V%bR(|
8 MEMBER FUNCTION SCIENT_OUTPUT(P_VALUE IN NUMBER) RETURN VARCHAR2,
7xoK&Y_2w/Y0 9 STATIC FUNCTION F_MULTI_SUM_OBJECT(P_IN IN NUMBER, P_SIENCT IN NUMBER DEFAULT NULL) RETURN VARCHAR2 ITPUB个人空间\Z%G+fpW!G(~!EsL
10 );
Ak7JAVv0 11 /
类型已创建。
SQL> CREATE OR REPLACE TYPE BODY T_BIG_NUMBER ASITPUB个人空间MX,kR3E
2 STATIC FUNCTION F_T_BIG_NUMBER (P_BIG_NUMBER IN VARCHAR2) RETURN T_BIG_NUMBER AS
ro,tt+lc4q__0 3 V_RESULT T_BIG_NUMBER := T_BIG_NUMBER('0', 1);
xO/W#HDQ'T0 4 BEGIN
'k_KM8V[0 5 V_RESULT.BIG_NUMBER := P_BIG_NUMBER;
,F7M+A_$^Z@0 6 V_RESULT.NUMBER_LENGTH := LENGTH(P_BIG_NUMBER);ITPUB个人空间B`:p.m:m y*C
7 RETURN V_RESULT;ITPUB个人空间.z\R/q
h|N
8 END; ITPUB个人空间VY&p
BOZ
9
+c![qCZG{0 10 MEMBER FUNCTION ADDS (P_ADD IN T_BIG_NUMBER) RETURN T_BIG_NUMBER ASITPUB个人空间3jcwVo
11 V_FLAG NUMBER(1) DEFAULT 0;
#m9?Ou@ T|9uEr8J0 12 V_RESULT T_BIG_NUMBER := T_BIG_NUMBER(NULL, 0);ITPUB个人空间(I,n%YP7w!f
13 V_SUM NUMBER;ITPUB个人空间?Z0r:Nn$g/~e8r
14 V_MAX_LENGTH NUMBER DEFAULT GREATEST(NUMBER_LENGTH, P_ADD.NUMBER_LENGTH);