由于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中国
作者
相关推荐
-
Collaborate 18大会:了解甲骨文云数据库和应用的进展
在Collaborate 18大会即将举行时,我们会发现,甲骨文用户社区的技术变化会略高于平常水平。 由独立甲 […]
-
甲骨文自治数据库亮相 带来云计算新希望
早前甲骨文还不在云计算公司之列,而现在该公司正在迅速弥补其失去的时间。甲骨文的云计算核心是甲骨文自治数据库(O […]
-
2017年12月数据库流行度排行榜 定格岁末排名瞬间
数据库知识网站DB-engines最近更新的2017年12月份数据库流行度排名情况是否能提供更多的看点呢?TechTarget数据库网站将与您分享12月份的榜单排名情况,让我们拭目以待。
-
2017年11月数据库流行度排行榜 半数以上数据库积分减少
数据库知识网站DB-engines更新了2016年11月份的数据库流行度排行榜。TechTarget数据库网站将与您一同关注11月份的榜单排名情况。