Plsql 在过程或函数中执行时,算术运算的结果不准确(oracle)

Plsql 在过程或函数中执行时,算术运算的结果不准确(oracle),plsql,numbers,decimal-point,Plsql,Numbers,Decimal Point,我试图计算受员工工资影响的项目,但算术运算的结果不准确,例如返回99.9999999999而不是100。这只发生在过程或函数内部,但在单独的sql查询中可以正常工作 例: 实际结果是:99.99 预期结果:100 外部程序给出了预期的结果 从双通道选择(100/30)*30 产量:100 因为其他数字都有分数部分,所以为什么和如何避免在不舍入数字的情况下出现这种情况? 谢谢,编辑:好的,现在问题稍微清楚了,这个过程产生了99.9循环,这与100不同,特别是当你四舍五入时。然而,我仍然没有看到PL

我试图计算受员工工资影响的项目,但算术运算的结果不准确,例如返回99.9999999999而不是100。这只发生在过程或函数内部,但在单独的sql查询中可以正常工作

例:

实际结果是:99.99 预期结果:100

外部程序给出了预期的结果

从双通道选择(100/30)*30
产量:100

因为其他数字都有分数部分,所以为什么和如何避免在不舍入数字的情况下出现这种情况?
谢谢,

编辑:好的,现在问题稍微清楚了,这个过程产生了99.9循环,这与100不同,特别是当你四舍五入时。然而,我仍然没有看到PL/SQL在SQL正确的地方给出错误的结果。正如鲍勃的回答所示,
100/30*30
(100*30)/30
是两件不同的事情


这是一个显示格式问题(编辑:除非向下取整…):

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.

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

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为零,则按预期工作


祝你好运。

申报tot编号(10)也就是说,如果你不关心精度,如果你做
声明tot数(10,5)或任何其他。。。如果有效,请告诉我。@g00dy。你的建议当然行,但问题是OP不知道他想要什么。我仍在等待来自的
实际结果
定义him@XING-正确,还没有实际的结果定义…请共享“正确运行”的“分离sql查询”。请参阅下面我的答案。演示原始计算始终生成99.999999999999999999999999999999999999999999999999000的结果-您只需将其格式化为足够宽即可看到它。我怀疑您使用的任何SQL工具都会取整查询结果,而PL/SQL结果没有取整。如果您按照我的回答重新排序计算中的操作,您将得到预期的结果。即使@g00dy编写的内容也会带来OP问题中需要的内容。“不确定你想用这个答案说明什么,@William Robertson在程序中调试时,手表的值是99.99999999,并在其他计算中使用此结果,而不将其保存在表格中。最终结果将根据99得出。”。9999999@sahar这是你的假设。调试器很可能将所有值显示为字符串(例如,请参见它对日期的处理)。99.9是字符串的外观,100是数字的外观。请尝试此显示,它不仅影响显示,还影响计算。将表创建表SS_测试_切割(切割编号)创建或替换程序SS_测试(x1编号、x2编号、num out编号)中存储的值视为x编号;开始x:=100;数值:=(x/30)*(30-x1-x2);插入ss_测试_切割(切割)值(trunc(num,2));终止这里的问题是计算中的中间舍入(x/30
),然后通过乘法通过剩余的操作进行传播。如果计算机实现了无限精度的数学运算,这并不重要——但事实并非如此。解决方案是简单地重新安排操作,将除法延迟到我在下面的回答中提到的计算结束。谢谢,非常好。我猜99.9和100在四舍五入时是不一样的。然而@sahar建议他的计算在SQL和PL/SQL中给出了不同的结果,而PL/SQL给出了不正确的结果,但他没有演示。我想你的答案解决了实际问题,剩下的是XY问题。这表明问题在于计算,而不是调用它的位置和方式。我在问题上添加了一条评论,以引起OP的注意。
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.
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;