在程序或函数中执行时的算术运算不正确结果(oracle)

问题描述:

我试图计算受员工薪水影响的项目,但算术运算的结果不准确,因为示例返回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

编辑:好了,现在的问题是稍微明朗,过程是生产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是它看起来像一个数字。 –

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

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的注意。 –