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

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

  上面一篇已经介绍了如何实现整数的字符串相减,有了这个作为基础,只需要分别对整数和小数部分分别处理,并将结果规整返回即可:






SQL> create OR REPLACE FUNCTION F_STR_SUB(P_STR1 IN VARchar2, P_STR2 IN VARchar2) RETURN VARchar2 AS

3 V_INTEGER_STR1 VARchar2(32767) := NVL(
4 SUBSTR(P_STR1, 1, 
5 CASE INSTR(P_STR1, ’.’) WHEN 0 THEN LENGTH(P_STR1) ELSE INSTR(P_STR1, ’.’) – 1 END
6 ), 0);
7 V_INTEGER_STR2 VARchar2(32767) := NVL(
8 SUBSTR(P_STR2, 1, 
9 CASE INSTR(P_STR2, ’.’) WHEN 0 THEN LENGTH(P_STR2) ELSE INSTR(P_STR2, ’.’) – 1 END
10 ), 0);
11 V_OTHER_STR1 VARchar2(32767) := CASE INSTR(P_STR1, ’.’) 
12 WHEN 0 THEN NULL ELSE SUBSTR(P_STR1, INSTR(P_STR1, ’.’) + 1) END;
13 V_OTHER_STR2 VARchar2(32767) := CASE INSTR(P_STR2, ’.’) 
14 WHEN 0 THEN NULL ELSE SUBSTR(P_STR2, INSTR(P_STR2, ’.’) + 1) END;
15 V_LENGTH_OTHER_1 NUMBER := NVL(LENGTH(V_OTHER_STR1), 0);
16 V_LENGTH_OTHER_2 NUMBER := NVL(LENGTH(V_OTHER_STR2), 0);
17 V_RESULT1 VARchar2(32767);
18 V_RESULT2 VARchar2(32767);
19 
20 FUNCTION F_SUB_STR(P_SUB1 IN VARchar2, P_SUB2 IN VARchar2) RETURN VARchar2 AS
21 V_LENGTH1 NUMBER DEFAULT LENGTH(P_SUB1);
22 V_LENGTH2 NUMBER DEFAULT LENGTH(P_SUB2);
23 V_RES1 VARchar2(32767);
24 V_RES2 VARchar2(32767);
25 BEGIN
26 IF SUBSTR(P_SUB1, 1, 1) = ’-’ THEN
27 IF SUBSTR(P_SUB2, 1, 1) = ’-’ THEN
28 RETURN F_SUB_STR(SUBSTR(P_SUB2, 2), SUBSTR(P_SUB1, 2));
29 ELSE
30 RETURN ’-’ || F_STR_ADD(SUBSTR(P_SUB1, 2), P_SUB2);
31 END IF;
32 ELSE
33 IF SUBSTR(P_SUB2, 1, 1) = ’-’ THEN
34 RETURN F_STR_ADD(SUBSTR(P_SUB1, 2), P_SUB2);
35 END IF;
36 END IF;
37 IF V_LENGTH1 > 37 AND V_LENGTH2 > 37 THEN 
38 V_RES1 := F_SUB_STR(SUBSTR(P_SUB1, 1, V_LENGTH1 – 37), SUBSTR(P_SUB2, 1, V_LENGTH2 – 37));
39 V_RES2 := F_SUB_STR(SUBSTR(P_SUB1, V_LENGTH1 – 36), SUBSTR(P_SUB2, V_LENGTH2 – 36));
40 IF SUBSTR(V_RES1, 1, 1) = ’-’ THEN
41 IF SUBSTR(V_RES2, 1, 1) = ’-’ OR LTRIM(V_RES2, ’0’) IS NULL THEN
42 RETURN V_RES1 || SUBSTR(V_RES2, 2);
43 ELSE
44 RETURN ’-’ || F_SUB_STR(SUBSTR(V_RES1, 2), ’1’) 
45 || F_STR_ADD(F_SUB_STR(LPAD(’9’, 37, ’9’), V_RES2), ’1’);
46 END IF;
47 ELSIF LTRIM(V_RES1, ’0’) IS NULL THEN
48 RETURN V_RES2;
49 ELSE
50 IF SUBSTR(V_RES2, 1, 1) = ’-’ THEN
51 RETURN F_SUB_STR(V_RES1, 1) 
52 || F_STR_ADD(F_SUB_STR(LPAD(’9’, 37, ’9’), SUBSTR(V_RES2, 2)), ’1’);
53 ELSE
54 RETURN V_RES1 || V_RES2;
55 END IF;
56 END IF;
57 ELSIF V_LENGTH2 > 37 THEN
58 V_RES1 := F_SUB_STR(’0’, SUBSTR(P_SUB2, 1, V_LENGTH2 – 37));
59 V_RES2 := F_SUB_STR(P_SUB1, SUBSTR(P_SUB2, V_LENGTH2 – 36)); 
60 IF SUBSTR(V_RES1, 1, 1) = ’-’ THEN
61 IF SUBSTR(V_RES2, 1, 1) = ’-’ OR LTRIM(V_RES2, ’0’) IS NULL THEN
62 RETURN V_RES1 || SUBSTR(V_RES2, 2);
63 ELSE
64 RETURN ’-’ || F_SUB_STR(SUBSTR(V_RES1, 2), ’1’) 
65 || F_STR_ADD(F_SUB_STR(LPAD(’9’, 37, ’9’), V_RES2), ’1’);
66 END IF;
67 ELSIF LTRIM(V_RES1, ’0’) IS NULL THEN
68 RETURN V_RES2;
69 ELSE
70 IF SUBSTR(V_RES2, 1, 1) = ’-’ THEN
71 RETURN F_SUB_STR(V_RES1, 1) 
72 || F_STR_ADD(F_SUB_STR(LPAD(’9’, 37, ’9’), SUBSTR(V_RES2, 2)), ’1’);
73 ELSE
74 RETURN V_RES1 || V_RES2;
75 END IF;
76 END IF;
77 ELSIF V_LENGTH1 > 37 THEN
78 V_RES1 := SUBSTR(P_SUB1, 1, V_LENGTH1 – 37);
79 V_RES2 := F_SUB_STR(SUBSTR(P_SUB1, V_LENGTH1 – 36), P_SUB2);
80 IF SUBSTR(V_RES1, 1, 1) = ’-’ THEN
81 IF SUBSTR(V_RES2, 1, 1) = ’-’ OR LTRIM(V_RES2, ’0’) IS NULL THEN
82 RETURN V_RES1 || SUBSTR(V_RES2, 2);
83 ELSE
84 RETURN ’-’ || F_SUB_STR(SUBSTR(V_RES1, 2), ’1’) 
85 || F_STR_ADD(F_SUB_STR(LPAD(’9’, 37, ’9’), V_RES2), ’1’);
86 END IF;
87 ELSIF LTRIM(V_RES1, ’0’) IS NULL THEN
88 RETURN V_RES2;
89 ELSE
90 IF SUBSTR(V_RES2, 1, 1) = ’-’ THEN
91 RETURN F_SUB_STR(V_RES1, 1) 
92 || F_STR_ADD(F_SUB_STR(LPAD(’9’, 37, ’9’), SUBSTR(V_RES2, 2)), ’1’);
93 ELSE
94 RETURN V_RES1 || V_RES2;
95 END IF;
96 END IF;
97 ELSE
98 RETURN SUBSTR(SIGN(TO_NUMBER(P_SUB1) – TO_NUMBER(P_SUB2)), -2, 1) 
99 || LPAD(ABS(TO_NUMBER(P_SUB1) – TO_NUMBER(P_SUB2)), GREATEST(V_LENGTH1, V_LENGTH2), ’0’);
100 END IF;
101 END;
102 
103 BEGIN
104 V_RESULT1 := F_SUB_STR(V_INTEGER_STR1, V_INTEGER_STR2);
105 V_RESULT2 := F_SUB_STR(RPAD(V_OTHER_STR1, GREATEST(V_LENGTH_OTHER_1, V_LENGTH_OTHER_2), ’0’), 
106 RPAD(V_OTHER_STR2, GREATEST(V_LENGTH_OTHER_1, V_LENGTH_OTHER_2), ’0’));
107 
108 IF SUBSTR(V_RESULT1, 1, 1) = ’-’ THEN
109 IF SUBSTR(V_RESULT2, 1, 1) = ’-’ OR LTRIM(V_RESULT2, ’0’) IS NULL THEN
110 RETURN ’-’ || NVL(LTRIM(RTRIM(RTRIM(SUBSTR(V_RESULT1, 2) || ’.’ || SUBSTR(V_RESULT2, 2), ’0’), ’.’), ’0’), ’0’);
111 ELSE
112 RETURN ’-’ || NVL(LTRIM(RTRIM(RTRIM(F_SUB_STR(SUBSTR(V_RESULT1, 2), ’1’) || ’.’ 
113 || F_STR_ADD(F_SUB_STR(LPAD(’9’, LENGTH(V_RESULT2), ’9’), V_RESULT2), ’1’)
114 , ’0’), ’.’), ’0’), ’0’);
115 END IF;
116 ELSIF LTRIM(V_RESULT1, ’0’) IS NULL THEN
117 RETURN NVL(RTRIM(’.’ || RTRIM(V_RESULT2, ’0’), ’.’), 0);
118 ELSE
119 IF SUBSTR(V_RESULT2, 1, 1) = ’-’ THEN
120 RETURN NVL(LTRIM(RTRIM(RTRIM(F_SUB_STR(V_RESULT1, ’1’) || ’.’ 
121 || F_STR_ADD(F_SUB_STR(LPAD(’9’, LENGTH(V_RESULT2), ’9’), SUBSTR(V_RESULT2, 2)), ’1’)
122 , ’0’), ’.’), ’0’), ’0’);
123 ELSE
124 RETURN NVL(LTRIM(RTRIM(RTRIM(V_RESULT1 || ’.’ || V_RESULT2, ’0’), ’.’), ’0’), ’0’);
125 END IF;
126 END IF;
127 END;
128 /
函数已创建。


  通过几个简单的例子验证一下结果:







SQL> select F_STR_SUB(’123.1293482734982379482374’, 
2 ’812384.123412834991238234823794822342’) FROM DUAL;
F_STR_SUB(’123.1293482734982379482374’,’812384.123412834991238234823794822342’)
——————————————————————————–
-812260.994064561493000286586394822342
SQL> select F_STR_SUB(’812384.123412834991238234823794822342’, 
2 ’123.1293482734982379482374’) FROM DUAL;
F_STR_SUB(’812384.123412834991238234823794822342’,’123.1293482734982379482374’)
——————————————————————————–
812260.9994064561493000286586394822342
SQL> select F_STR_SUB(’812384.1293482734982379482374’, 
2 ’123.123412834991238234823794822342’) FROM DUAL;
F_STR_SUB(’812384.1293482734982379482374’,’123.123412834991238234823794822342’)
——————————————————————————–
812261.005935438506999713413605177658
SQL> select F_STR_SUB(’123.123412834991238234823794822342’,
2 ’812384.1293482734982379482374’) FROM DUAL;
F_STR_SUB(’123.123412834991238234823794822342’,’812384.1293482734982379482374’)
——————————————————————————–

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

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

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

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

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

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

相关推荐