yangtingkun
===========================================================
利用字符串实现高精度数值运算(五)
===========================================================

由于Oracle的数值类型的最大精度只有38位,因此对于高精度的数值计算就需要使用其他的方法来实现。

这篇文章利用字符串来保存高精度数值,并实现了两个字符串中数值的运算。

这篇给出基础的字符串除法的解决方案。

利用字符串实现高精度数值运算(一):http://yangtingkun.itpub.net/post/468/469206

利用字符串实现高精度数值运算(二):http://yangtingkun.itpub.net/post/468/469241

利用字符串实现高精度数值运算(三):http://yangtingkun.itpub.net/post/468/469423

利用字符串实现高精度数值运算(四):http://yangtingkun.itpub.net/post/468/469550


由于除法相对其他算法而言,比较复杂,因此将除法的计算分拆到多篇文章中进行描述。

这里实现一个最简单的除法运算,无论是除数还是被除数都没有超过OracleNUMBER类型的精度范围。

SQL> CREATE OR REPLACE FUNCTION F_DIVITE_STR(P_DIVITED IN VARCHAR2, P_DIVITING IN VARCHAR2) RETURN V
ARCHAR2 AS
2 V_RESULT VARCHAR2(32767) := SUBSTR(TO_NUMBER(P_DIVITED) / TO_NUMBER(P_DIVITING), 1, 37);
3 V_COUNT NUMBER := 1;
4 P_PERCISION NUMBER DEFAULT 101;
5 V_LENGTH NUMBER := -1;
6 BEGIN
7
8 LOOP
9 DBMS_OUTPUT.PUT_LINE(V_RESULT);
10 EXIT WHEN LENGTH(V_RESULT) > P_PERCISION
11 OR V_LENGTH = CASE WHEN INSTR(V_RESULT, '.') > 0 THEN LENGTH(RTRIM(RTRIM(V_RESULT, '0'), '.'
)) ELSE LENGTH(V_RESULT) END;
12 V_LENGTH := LENGTH(V_RESULT);
13 V_COUNT := V_COUNT + 1;
14
15 V_RESULT := V_RESULT ||
16 REPLACE(SUBSTR(TO_NUMBER(F_STR_MULTI(F_STR_SUB(P_DIVITED, F_STR_MULTI(V_RESULT, P_DIVITING))
, RPAD(1, 37 * V_COUNT, '0')))
17 / TO_NUMBER(P_DIVITING), 1, 37), '.', '');
18
19 END LOOP;
20 RETURN V_RESULT;
21 END;
22 /

函数已创建。

这里首先计算最简单的被除数和除数都可以通过NUMBER类型精度表示的数值相除。不过由于除法的特殊性,这里引入了另一个参数,来指定除法保留的小数位数。

除法的计算没有再使用加法、减法和乘法程序使用的递归算法,而是采用了循环算法。当小数位数满足需要,或者余数为0时,退出循环,返回最终结果。

简单的测试一下:

SQL> SELECT F_DIVITE_STR('100', '3') FROM DUAL;

F_DIVITE_STR('100','3')
-------------------------------------------------------------------------------------------
33.3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333

SQL> SELECT F_DIVITE_STR('1', '7') FROM DUAL;

F_DIVITE_STR('1','7')
-------------------------------------------------------------------------------------------
.142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142

SQL> SELECT F_DIVITE_STR('0.2', '0.011') FROM DUAL;

F_DIVITE_STR('0.2','0.011')
-------------------------------------------------------------------------------------------
18.1818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181

yangtingkun 发表于:2008.08.30 23:50 ::分类: ( ORACLE ) ::阅读:(5226次) :: 评论 (0)

发表评论
标题

在此添加评论
表情符号: smile laughing tongue angry crying sad wassat wink

称呼

邮箱地址(可选)

个人主页(可选)

 authimage


切换风格
新闻聚合
博客日历
文章归档...
最新发表...
最新评论...
最多阅读文章...
最多评论文章...
博客统计...
Blog信息
网站链接...