2017-09-13 60 views
-2

我試圖計算受員工薪水影響的項目,但算術運算的結果不準確,因爲示例返回99.99999999999999而不是100。這隻發生在程序或函數內,但在分離的sql查詢中正常工作。在程序或函數中執行時的算術運算不正確結果(oracle)

EX:

CREATE TABLE SS_TEST_CUT 
(
    CUT NUMBER 
); 

create or replace procedure ss_test (x1 number , x2 number , num out number) 
as 
x number ; 
begin 
    x := 100; 
    num := (x/30) *(30 - x1 - x2); 
    insert into ss_test_cut (cut) values (trunc (num,2)); 
end; 

select cut from ss_test_cut; 

實際結果是:99.99 預期結果:100

出側的過程給出預期的結果。

select (100/30) * 30 from dual; 輸出:100

爲何以及如何與不圓數量,以避免這一點,因爲其他的數字有小數部分? 謝謝,

+0

'聲明總數(10);'也就是說,如果你不關心精度,如果你聲明總數(10,5);'或者其他任何...讓我知道它是否可行。 – g00dy

+0

@ g00dy。你的建議肯定會奏效,但問題是OP不知道他想要什麼。 :-)。我仍在等待他的實際結果定義 – XING

+0

@XING - true,沒有實際的結果定義... – g00dy

回答

1

編輯:好了,現在的問題是稍微明朗,過程是生產99.9經常性,這是不一樣的東西100,尤其是當你向下取整。但是,我仍然沒有看到PL/SQL在SQL正確的地方給出了錯誤的結果。正如鮑勃的答案所示,100/30 * 30(100 * 30)/30是兩個不同的東西。


這是一個顯示格式問題(編輯:除非你四捨五入...)

SQL> select 100/30 * 30 from dual; 

100/30*30 
---------- 
     100 

SQL> select to_char(100/30 * 30) from dual; 

TO_CHAR(100/30*30) 
---------------------------------------- 
99.9999999999999999999999999999999999999 

99.9復發和100實際上是相同的事情。

下面是另一個例子,以顯示該程序內的結果是相同的直接使用SQL時爲:

SQL> create table demo (label varchar2(10), result number); 

Table created. 

SQL> insert into demo values ('SQL', 100/30 * 30); 

1 row created. 

SQL> declare 
    2  num number; 
    3 begin 
    4  num := 100/30 * 30; 
    5 
    6  insert into demo values ('PL/SQL', num); 
    7 end; 
    8/

PL/SQL procedure successfully completed. 

SQL> select label, result, to_char(result) from demo; 

LABEL   RESULT TO_CHAR(RESULT) 
---------- ---------- ---------------------------------------- 
SQL    100 99.9999999999999999999999999999999999999 
PL/SQL   100 99.9999999999999999999999999999999999999 

2 rows selected. 
+0

即使@ g00dy寫了什麼會帶來OP問題中所需的內容。不知道你想用這個答案做什麼, – XING

+0

@William Robertson在程序中調試時的值爲99.999999999,並將此結果用於其他計算中並將其保存在表中,最終結果將按照99.9999999 – sahar

+0

@sahar那是你的假設。調試器最有可能將所有值顯示爲字符串(例如,查看它對日期所做的操作)。 99.9經常性是它看起來像一個字符串,100是它看起來像一個數字。 –

1

重新排序在計算中操作,以避免中間舍入:

create or replace procedure ss_test (x1 number , x2 number , num out number) 
as 
x number ; 
begin 
    x := 100; 
    num := (x * (30 - x1 - x2))/30; 
    insert into ss_test_cut (cut) values (trunc (num,2)); 
end; 

按預期工作,假設x1和x2爲零。

祝你好運。

+0

優秀點。我猜99.9經常出現的情況與下降時的100不一樣。然而,@sahar建議他在SQL和使用PL/SQL的PL/SQL中給出不同的結果給出了不正確的結果,這是他沒有證明的。我想你的答案可以解決實際問題,剩下的就是XY問題。 –

+0

[我剛剛創建了一個SQLFiddle](http://sqlfiddle.com/#!4/a157f/1),它表明問題是計算而不是在何處以及如何調用。我爲這個問題添加了一條評論,以引起OP的注意。 –