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

日期: 2008-08-27 作者:杨廷琨 来源:TechTarget中国 英文

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


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


  这篇描述两个表示整数的字符串相减。


  上一篇给出了字符串相乘的算法,这一篇继续探讨减法的实现。由于前两篇文章实际上都使用了以前实现的整数部分的代码,而这一篇则没有相应的代码可以重用。


  因此模仿前面的实现,将这个复杂的问题拆分成两个相对简单一些的问题,首先实现整数部分的减法,然后再扩展到小数部分。







SQL> create OR REPLACE FUNCTION F_SUB_STR(P_SUB1 IN VARchar2, P_SUB2 IN VARchar2) RETURN VARchar2 AS
2 V_LENGTH1 NUMBER DEFAULT LENGTH(P_SUB1);
3 V_LENGTH2 NUMBER DEFAULT LENGTH(P_SUB2);
4 V_RES1 VARchar2(32767);
5 V_RES2 VARchar2(32767);
6 BEGIN
7 IF SUBSTR(P_SUB1, 1, 1) = ’-’ THEN
8 IF SUBSTR(P_SUB2, 1, 1) = ’-’ THEN
9 RETURN F_SUB_STR(SUBSTR(P_SUB2, 2), SUBSTR(P_SUB1, 2));
10 ELSE
11 RETURN ’-’ || F_STR_ADD(SUBSTR(P_SUB1, 2), P_SUB2);
12 END IF;
13 ELSE
14 IF SUBSTR(P_SUB2, 1, 1) = ’-’ THEN
15 RETURN F_STR_ADD(SUBSTR(P_SUB1, 2), P_SUB2);
16 END IF;
17 END IF;
18 IF V_LENGTH1 > 37 AND V_LENGTH2 > 37 THEN 
19 V_RES1 := F_SUB_STR(SUBSTR(P_SUB1, 1, V_LENGTH1 – 37), SUBSTR(P_SUB2, 1, V_LENGTH2 – 37));
20 V_RES2 := F_SUB_STR(SUBSTR(P_SUB1, V_LENGTH1 – 36), SUBSTR(P_SUB2, V_LENGTH2 – 36));
21 IF SUBSTR(V_RES1, 1, 1) = ’-’ THEN
22 IF SUBSTR(V_RES2, 1, 1) = ’-’ THEN
23 RETURN V_RES1 || SUBSTR(V_RES2, 2);
24 ELSE
25 RETURN ’-’ || F_SUB_STR(SUBSTR(V_RES1, 2), ’1’) 
26 || F_STR_ADD(F_SUB_STR(LPAD(’9’, 37, ’9’), V_RES2), ’1’);
27 END IF;
28 ELSIF LTRIM(V_RES1, ’0’) IS NULL THEN
29 RETURN V_RES2;
30 ELSE
31 IF SUBSTR(V_RES2, 1, 1) = ’-’ THEN
32 RETURN F_SUB_STR(V_RES1, 1) 
33 || F_STR_ADD(F_SUB_STR(LPAD(’9’, 37, ’9’), SUBSTR(V_RES2, 2)), ’1’);
34 ELSE
35 RETURN V_RES1 || V_RES2;
36 END IF;
37 END IF;
38 ELSIF V_LENGTH2 > 37 THEN
39 V_RES1 := F_SUB_STR(’0’, SUBSTR(P_SUB2, 1, V_LENGTH2 – 37));
40 V_RES2 := F_SUB_STR(P_SUB1, SUBSTR(P_SUB2, V_LENGTH2 – 36)); 
41 IF SUBSTR(V_RES1, 1, 1) = ’-’ THEN
42 IF SUBSTR(V_RES2, 1, 1) = ’-’ THEN
43 RETURN V_RES1 || SUBSTR(V_RES2, 2);
44 ELSE
45 RETURN ’-’ || F_SUB_STR(SUBSTR(V_RES1, 2), ’1’) 
46 || F_STR_ADD(F_SUB_STR(LPAD(’9’, 37, ’9’), V_RES2), ’1’);
47 END IF;
48 ELSIF LTRIM(V_RES1, ’0’) IS NULL THEN
49 RETURN V_RES2;
50 ELSE
51 IF SUBSTR(V_RES2, 1, 1) = ’-’ THEN
52 RETURN F_SUB_STR(V_RES1, 1) 
53 || F_STR_ADD(F_SUB_STR(LPAD(’9’, 37, ’9’), SUBSTR(V_RES2, 2)), ’1’);
54 ELSE
55 RETURN V_RES1 || V_RES2;
56 END IF;
57 END IF;
58 ELSIF V_LENGTH1 > 37 THEN
59 V_RES1 := SUBSTR(P_SUB1, 1, V_LENGTH1 – 37);
60 V_RES2 := F_SUB_STR(SUBSTR(P_SUB1, V_LENGTH1 – 36), P_SUB2);
61 IF SUBSTR(V_RES1, 1, 1) = ’-’ THEN
62 IF SUBSTR(V_RES2, 1, 1) = ’-’ THEN
63 RETURN V_RES1 || SUBSTR(V_RES2, 2);
64 ELSE
65 RETURN ’-’ || F_SUB_STR(SUBSTR(V_RES1, 2), ’1’) 
66 || F_STR_ADD(F_SUB_STR(LPAD(’9’, 37, ’9’), V_RES2), ’1’);
67 END IF;
68 ELSIF LTRIM(V_RES1, ’0’) IS NULL THEN
69 RETURN V_RES2;
70 ELSE
71 IF SUBSTR(V_RES2, 1, 1) = ’-’ THEN
72 RETURN F_SUB_STR(V_RES1, 1) 
73 || F_STR_ADD(F_SUB_STR(LPAD(’9’, 37, ’9’), SUBSTR(V_RES2, 2)), ’1’);
74 ELSE
75 RETURN V_RES1 || V_RES2;
76 END IF;
77 END IF;
78 ELSE
79 RETURN SIGN(TO_NUMBER(P_SUB1) – TO_NUMBER(P_SUB2)) *
80 LPAD(ABS(TO_NUMBER(P_SUB1) – TO_NUMBER(P_SUB2)), GREATEST(V_LENGTH1, V_LENGTH2), ’0’);
81 END IF;
82 END;
83 /
函数已创建。


  下面验证一下:







SQL> select F_SUB_STR(’123451234512345’, ’5432154321’) FROM DUAL;
F_SUB_STR(’123451234512345’,’5432154321’)
——————————————————————————–
123445802358024
SQL> select F_SUB_STR(’5432154321’, ’123451234512345’) FROM DUAL;
F_SUB_STR(’5432154321’,’123451234512345’)
——————————————————————————–
-123445802358024
SQL> select F_SUB_STR(’55555555555555555555555555555555555555’, ’2222222222222’) FROM DUAL;
F_SUB_STR(’55555555555555555555555555555555555555’,’2222222222222’)
——————————————————————————–
55555555555555555555555553333333333333
SQL> select F_SUB_STR(’55555555555555555555555555555555555555’, 
2 ’2222222222222222222222222222222222222222222222222’) FROM DUAL;
F_SUB_STR(’55555555555555555555555555555555555555’,’2222222222222222222222222222
——————————————————————————–
-2222222222166666666666666666666666666666666666667
SQL> select F_SUB_STR(’55555555555555555555555555555555555555’, 
2 ’66666666666666666666666666666666666666’) FROM DUAL;
F_SUB_STR(’55555555555555555555555555555555555555’,’6666666666666666666666666666
——————————————————————————–
-11111111111111111111111111111111111111
SQL> select F_SUB_STR(’555555555555555555555555555555555555555’,
2 ’66666666666666666666666666666666666666’) FROM DUAL;
F_SUB_STR(’555555555555555555555555555555555555555’,’666666666666666666666666666

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

电子邮件地址不会被公开。 必填项已用*标注

敬请读者发表评论,本站保留删除与本文无关和不雅评论的权力。

相关推荐