利用字串實現高精度數值運算(四)
由於Oracle的數值型別的最大精度只有38位,因此對於高精度的數值計算就需要使用其他的方法來實現。
這篇文章利用字串來儲存高精度數值,並實現了兩個字串中數值的運算。
這篇給出完整的字串相減的解決方法。
利用字串實現高精度數值運算(一):http://yangtingkun.itpub.net/post/468/469206
利用字串實現高精度數值運算(二):http://yangtingkun.itpub.net/post/468/469241
利用字串實現高精度數值運算(三):http://yangtingkun.itpub.net/post/468/469423
上面一篇已經介紹瞭如何實現整數的字串相減,有了這個作為基礎,只需要分別對整數和小數部分分別處理,並將結果規整返回即可:
SQL> CREATE OR REPLACE FUNCTION F_STR_SUB(P_STR1 IN VARCHAR2, P_STR2 IN VARCHAR2) RETURN VARCHAR2 AS
2
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_ADD_STR(SUBSTR(P_SUB1, 2), P_SUB2);
31 END IF;
32 ELSE
33 IF SUBSTR(P_SUB2, 1, 1) = '-' THEN
34 RETURN F_ADD_STR(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_ADD_STR(F_SUB_STR(LPAD('9', 37, '9'), V_RES2), LPAD('1', 37, '0'));
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_ADD_STR(F_SUB_STR(LPAD('9', 37, '9'), SUBSTR(V_RES2, 2)), LPAD('1', 37, '0'));
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_ADD_STR(F_SUB_STR(LPAD('9', 37, '9'), V_RES2), LPAD('1', 37, '0'));
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_ADD_STR(F_SUB_STR(LPAD('9', 37, '9'), SUBSTR(V_RES2, 2)), LPAD('1', 37, '0'));
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_ADD_STR(F_SUB_STR(LPAD('9', 37, '9'), V_RES2), LPAD('1', 37, '0'));
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_ADD_STR(F_SUB_STR(LPAD('9', 37, '9'), SUBSTR(V_RES2, 2)), LPAD('1', 37, '0'));
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')
--------------------------------------------------------------------------------
-812261.005935438506999713413605177658
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-434854/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 利用字串實現高精度數值運算(三)字串
- 利用字串實現高精度數值運算(二)字串
- 利用字串實現高精度數值運算(一)字串
- 【Mysql學習】算術運算及字串,數值函式MySql字串函式
- 【Mysql 學習】算術運算及字串,數值函式MySql字串函式
- 四則運算實現 (轉)
- 複數的四則運算(C語言實現)C語言
- 利用ANTLR4實現一個簡單的四則運算計算器
- 簡單c++實現複數的四則運算C++
- SHELL之數值運算
- 使用位運算、值交換等方式反轉java字串-共四種方法Java字串
- Python基礎學習篇-2-數值運算和字串Python字串
- 高精度地圖量產難,四維圖新利用優勢準備實現突破地圖
- 大整數運算C#實現C#
- 兩個數換值四種方法實現
- XJSON 是如何實現四則運算的?JSON
- linux shell 實現 四則運算(整數及浮點) 簡單方法Linux
- Linux Shell 實現四則運算(整數及浮點)簡單方法Linux
- java大整數四則運算Java
- 計算機系統002 – 數值運算計算機
- 計算機系統002 - 數值運算計算機
- php鏈式操作實現四則鏈式運算PHP
- 實現四則運算的一條sql語句SQL
- 利用版本回退實現誤運算元據恢復
- 集合-運算實現
- 用python實現四則運算的生成與判定Python
- 5,javase程式碼實戰-運算子——位運算實現兩個變數的互換及其他方式(四)Java變數
- Java浮點數運算實現四捨五入和格式化方法總結Java
- (位運算)兩個字串的位運算字串
- 四則運算
- 【數值計算方法】常微分方程數值解-數值實驗
- 第二次作業: 四則運算的實現
- vue中使用decimal.js對前端數值型別進行高精度計算VueDecimalJS前端型別
- C++ std::list實現大整數加法運算C++
- 四則運算計算器
- 字串拼接運算比較字串
- .NET的數學庫NMath實用教程——複數的值操作和邏輯運算
- 如何用位運算實現整數的加減法