利用字串實現高精度數值運算(三)
由於Oracle的數值型別的最大精度只有38位,因此對於高精度的數值計算就需要使用其他的方法來實現。
這篇文章利用字串來儲存高精度數值,並實現了兩個字串中數值的運算。
這篇描述兩個表示整數的字串相減。
利用字串實現高精度數值運算(一):http://yangtingkun.itpub.net/post/468/469206
利用字串實現高精度數值運算(二):http://yangtingkun.itpub.net/post/468/469241
上一篇給出了字串相乘的演算法,這一篇繼續探討減法的實現。由於前兩篇文章實際上都使用了以前實現的整數部分的程式碼,而這一篇則沒有相應的程式碼可以重用。
因此模仿前面的實現,將這個複雜的問題拆分成兩個相對簡單一些的問題,首先實現整數部分的減法,然後再擴充套件到小數部分。
SQL> CREATE OR REPLACE FUNCTION F_ADD_STR(P_ADD1 IN VARCHAR2, P_ADD2 IN VARCHAR2) RETURN VARCHAR2 AS
2 V_LENGTH1 NUMBER DEFAULT LENGTH(P_ADD1);
3 V_LENGTH2 NUMBER DEFAULT LENGTH(P_ADD2);
4 BEGIN
5 IF V_LENGTH1 > 37 THEN
6 RETURN
7 F_ADD_STR
8 (
9 SUBSTR(P_ADD1, 1, V_LENGTH1 - 37),
10 NVL
11 (
12 SUBSTR
13 (
14 F_ADD_STR(SUBSTR(P_ADD1, V_LENGTH1 - 36), P_ADD2),
15 1,
16 LENGTH(F_ADD_STR(SUBSTR(P_ADD1, V_LENGTH1 - 36), P_ADD2)) - 37
17 ),
18 '0'
19 )
20 ) || SUBSTR(F_ADD_STR(SUBSTR(P_ADD1, V_LENGTH1 - 36), P_ADD2), - 37);
21 ELSIF V_LENGTH2 > 37 THEN
22 RETURN
23 F_ADD_STR
24 (
25 NVL
26 (
27 SUBSTR
28 (
29 F_ADD_STR(P_ADD1, SUBSTR(P_ADD2, V_LENGTH2 - 36)),
30 1,
31 LENGTH(F_ADD_STR(P_ADD1, SUBSTR(P_ADD2, V_LENGTH2 - 36))) - 37
32 ),
33 '0'
34 ),
35 SUBSTR(P_ADD2, 1, V_LENGTH2 - 37)
36 )
37 || SUBSTR(F_ADD_STR(P_ADD1, SUBSTR(P_ADD2, V_LENGTH2 - 36)), - 37);
38 ELSE
39 RETURN
40 LTRIM
41 (
42 TO_CHAR
43 (
44 TO_NUMBER(P_ADD1) + TO_NUMBER(P_ADD2),
45 RPAD
46 (
47 '0',
48 GREATEST(V_LENGTH1, V_LENGTH2, LENGTH(TO_NUMBER(P_ADD1) + TO_NUMBER(P_ADD2))),
49 '9'
50 )
51 )
52 );
53 END IF;
54 END;
55 /
函式已建立。
先建立F_STR_ADD函式,這個函式需要被F_SUB_STR呼叫,將其作為F_SUB_STR的內部函式沒有必要,而且會明顯增加程式碼的長度。
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_ADD_STR(SUBSTR(P_SUB1, 2), P_SUB2);
12 END IF;
13 ELSE
14 IF SUBSTR(P_SUB2, 1, 1) = '-' THEN
15 RETURN F_ADD_STR(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) = '-' OR LTRIM(V_RES2, '0') IS NULL THEN
23 RETURN V_RES1 || SUBSTR(V_RES2, 2);
24 ELSE
25 RETURN '-' || F_SUB_STR(SUBSTR(V_RES1, 2), '1')
26 || F_ADD_STR(F_SUB_STR(LPAD('9', 37, '9'), V_RES2), LPAD('1', 37, '0'));
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_ADD_STR(F_SUB_STR(LPAD('9', 37, '9'), SUBSTR(V_RES2, 2)), LPAD('1', 37, '0'));
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) = '-' OR LTRIM(V_RES2, '0') IS NULL THEN
43 RETURN V_RES1 || SUBSTR(V_RES2, 2);
44 ELSE
45 RETURN '-' || F_SUB_STR(SUBSTR(V_RES1, 2), '1')
46 || F_ADD_STR(F_SUB_STR(LPAD('9', 37, '9'), V_RES2), LPAD('1', 37, '0'));
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_ADD_STR(F_SUB_STR(LPAD('9', 37, '9'), SUBSTR(V_RES2, 2)), LPAD('1', 37, '0'));
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) = '-' OR LTRIM(V_RES2, '0') IS NULL THEN
63 RETURN V_RES1 || SUBSTR(V_RES2, 2);
64 ELSE
65 RETURN '-' || F_SUB_STR(SUBSTR(V_RES1, 2), '1')
66 || F_ADD_STR(F_SUB_STR(LPAD('9', 37, '9'), V_RES2), LPAD('1', 37, '0'));
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_ADD_STR(F_SUB_STR(LPAD('9', 37, '9'), SUBSTR(V_RES2, 2)), LPAD('1', 37, '0'));
74 ELSE
75 RETURN V_RES1 || V_RES2;
76 END IF;
77 END IF;
78 ELSE
79 RETURN SUBSTR(SIGN(TO_NUMBER(P_SUB1) - TO_NUMBER(P_SUB2)), -2, 1)
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
--------------------------------------------------------------------------------
488888888888888888888888888888888888889
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-434627/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 利用字串實現高精度數值運算(四)字串
- 利用字串實現高精度數值運算(二)字串
- 利用字串實現高精度數值運算(一)字串
- 【Mysql學習】算術運算及字串,數值函式MySql字串函式
- 【Mysql 學習】算術運算及字串,數值函式MySql字串函式
- SHELL之數值運算
- Python基礎學習篇-2-數值運算和字串Python字串
- 大整數運算C#實現C#
- 計算機系統002 – 數值運算計算機
- 計算機系統002 - 數值運算計算機
- 利用版本回退實現誤運算元據恢復
- 集合-運算實現
- (位運算)兩個字串的位運算字串
- 數值計算的可靠性(三)
- 【數值計算方法】常微分方程數值解-數值實驗
- vue中使用decimal.js對前端數值型別進行高精度計算VueDecimalJS前端型別
- 利用ANTLR4實現一個簡單的四則運算計算器
- python中字串基本操作以及三種位運算Python字串
- 複數的四則運算(C語言實現)C語言
- C++ std::list實現大整數加法運算C++
- 字串拼接運算比較字串
- .NET的數學庫NMath實用教程——複數的值操作和邏輯運算
- 如何用位運算實現整數的加減法
- 簡單c++實現複數的四則運算C++
- 【數值計算方法】非線性方程求根-數值實驗
- 位運算與SQL實現SQL
- 四則運算實現 (轉)
- C語言用三目運算實現判斷大寫C語言
- 關於int型別數值的運算問題型別
- 高精度計算合集
- oracle中字串的大小比較,字串與數字的比較和運算Oracle字串
- javascript怎麼實現算術加法運算JavaScript
- Shell階段02 shell變數運算(整數運算/小數運算), shell變數案例變數
- SCSS 顏色值運算CSS
- 位運算實現整數與位元組陣列轉換陣列
- 使用位運算、值交換等方式反轉java字串-共四種方法Java字串
- 圖解計算機中的數值範圍和浮點運算圖解計算機
- 如何從字串文字中拆解出多個數值並計算字串