由于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中国
作者
相关推荐
-
控制合约 不再畏惧Oracle
许多公司都与Oracle有无限制授权协议,他们害怕离开这个协议,所以就证明他们在使用Oracle的软件,即使因为需求单独购买部分授权许可也可能总体是省钱的。
-
如何应对Oracle EBS实施中的六个挑战?
在18个月的时间里,Vitamix启动运行了Oracle电子商务套件(E-Business Suite,EBS),而且Vitamix还对诸如Oracle ATG Web Commerce等所有页面属性进行了重新整理,并实现了全球数据中心。
-
DBA支招:如何实现Oracle EBS 12.2.5升级
那些对于是否要将EBS进行升级持观望态度的Oracle数据库管理员们可以从一家研究公司获得一些启示。
-
Oracle的云产品“砸了自己脚”?
Sparc和Solaris都是Oracle云计划的一部分,但是硬件和支持人员的减少意味着本地Solaris和Sparc将变得更加稀少。