利用字符串实现高精度数值运算
2008-08-27 12:43:53 来源:WEB开发网代码比较长,这里就不过多的描述实现了,下面简单看一下利用这个函数进行计算:
SQL>SELECTF_STR_ADD('12345.6789','98.7654321')FROMDUAL;
F_STR_ADD('12345.6789','98.7654321')
------------------------------------------------------------------------------------------
12444.4443321
SQL>SELECTF_STR_ADD('5555','12939')FROMDUAL;
F_STR_ADD('5555','12939')
------------------------------------------------------------------------------------------
18494
SQL>SELECTF_STR_ADD('0.234','74')FROMDUAL;
F_STR_ADD('0.234','74')
------------------------------------------------------------------------------------------
74.234
SQL>SELECTF_STR_ADD('0.00001111111111111111111111111111111111111','.234111111111111')FROMDUAL;
F_STR_ADD('0.00001111111111111111111111111111111111111','.234111111111111')
---------------------------------------------------------------------------------------
.23412222222222211111111111111111111111111
采用代码重用的方法,利用以前处理整数乘法的基础,加上小数部分的处理。整数部分算法描述可以参考:http://yangtingkun.itpub.net/post/468/241044
由于包含了小数部分,一个乘法变成4个乘法的相加,因此还要利用前面一篇文章的字符串相加的函数:
SQL>CREATEORREPLACEFUNCTIONF_STR_MULTI(P_STR1INVARCHAR2,P_STR2INVARCHAR2)RETURNVARCHAR2AS
2
3V_INTEGER_STR1VARCHAR2(32767):=NVL(
4SUBSTR(P_STR1,1,
5CASEINSTR(P_STR1,'.')WHEN0THENLENGTH(P_STR1)ELSEINSTR(P_STR1,'.')-1END
6),0);
7V_INTEGER_STR2VARCHAR2(32767):=NVL(
8SUBSTR(P_STR2,1,
9CASEINSTR(P_STR2,'.')WHEN0THENLENGTH(P_STR2)ELSEINSTR(P_STR2,'.')-1END
10),0);
11V_OTHER_STR1VARCHAR2(32767):=CASEINSTR(P_STR1,'.')
12WHEN0THENNULLELSESUBSTR(P_STR1,INSTR(P_STR1,'.')+1)END;
13V_OTHER_STR2VARCHAR2(32767):=CASEINSTR(P_STR2,'.')
14WHEN0THENNULLELSESUBSTR(P_STR2,INSTR(P_STR2,'.')+1)END;
15V_LENGTH_OTHER_1NUMBER:=NVL(LENGTH(V_OTHER_STR1),0);
16V_LENGTH_OTHER_2NUMBER:=NVL(LENGTH(V_OTHER_STR2),0);
17V_RESULT1VARCHAR2(32767);
18V_RESULT2VARCHAR2(32767);
19
20FUNCTIONF_MULTI_STR(P_MUL1INVARCHAR2,P_MUL2INVARCHAR2)RETURNVARCHAR2AS
21V_LENGTH1NUMBERDEFAULTLENGTH(P_MUL1);
22V_LENGTH2NUMBERDEFAULTLENGTH(P_MUL2);
23BEGIN
24IFV_LENGTH1>19THEN
25RETURNF_STR_ADD(F_MULTI_STR(SUBSTR(P_MUL1,1,V_LENGTH1-19),P_MUL2)||LPAD('0',19,'0'),
26F_MULTI_STR(SUBSTR(P_MUL1,V_LENGTH1-18),P_MUL2));
27ELSIFV_LENGTH2>19THEN
28RETURNF_STR_ADD(F_MULTI_STR(P_MUL1,SUBSTR(P_MUL2,1,V_LENGTH2-19))||LPAD('0',19,'0'),
29F_MULTI_STR(P_MUL1,SUBSTR(P_MUL2,V_LENGTH2-18)));
30ELSE
31RETURNTO_NUMBER(P_MUL1)*TO_NUMBER(P_MUL2);
32ENDIF;
33END;
34
35BEGIN
36V_RESULT1:=F_MULTI_STR(V_INTEGER_STR1,V_OTHER_STR2);
37V_RESULT2:=F_MULTI_STR(V_INTEGER_STR2,V_OTHER_STR1);
38V_RESULT1:=SUBSTR(V_RESULT1,1,LENGTH(V_RESULT1)-V_LENGTH_OTHER_2)
39||'.'
40||SUBSTR(V_RESULT1,-V_LENGTH_OTHER_2);
41V_RESULT2:=SUBSTR(V_RESULT2,1,LENGTH(V_RESULT2)-V_LENGTH_OTHER_1)
42||'.'
43||SUBSTR(V_RESULT2,-V_LENGTH_OTHER_1);
44RETURNLTRIM(RTRIM(RTRIM
45(
46F_STR_ADD
47(
48F_STR_ADD
49(
50F_MULTI_STR(V_INTEGER_STR1,V_INTEGER_STR2)
51||'.'
52||LPAD(
53F_MULTI_STR(V_OTHER_STR1,V_OTHER_STR2),
54V_LENGTH_OTHER_1+V_LENGTH_OTHER_2,
55'0'),
56V_RESULT1
57),
58V_RESULT2
59),
60'0'),'.'),'0'
61);
62END;
63/
函数已创建。
下面简单测试一下函数的功能:
SQL>SELECTF_STR_MULTI('12345678900987654321','555')FROMDUAL;
F_STR_MULTI('12345678900987654321','555')
------------------------------------------------------------------------
6851851790048148148155
SQL>SELECTF_STR_MULTI('1.2345678900987654321','555')FROMDUAL;
F_STR_MULTI('1.2345678900987654321','555')
------------------------------------------------------------------------
685.1851790048148148155
SQL>SELECTF_STR_MULTI('0.12345678900987654321','0.00555')FROMDUAL;
F_STR_MULTI('0.12345678900987654321','0.00555')
------------------------------------------------------------------------
.0006851851790048148148155
SQL>SELECTF_STR_MULTI('6.125','4.8')FROMDUAL;
F_STR_MULTI('6.125','4.8')
------------------------------------------------------------------------
29.4
SQL>SELECT12345678900987654321*555FROMDUAL;
12345678900987654321*555
------------------------
6.8519E+21
赞助商链接