db2 - 两个值相减时 SAS 得到错误结果

标签 db2 sas

全部,

我遇到了一些与 SAS 如何处理两个两位小数变量的减法相关的问题。这些结果被写入 DB2 数据库。这里使用的所有字段都导入到 SAS 并写入数据类型为 DECIMAL(19,2) 的 DB2 字段,问题如下:

             AL_AMT       - PL_AMT       = DIF_AMT
 From SAS:   9,918,322.38 - 9,942,322.30 = (23,999.91)
 Expected:   9,918,322.38 - 9,942,322.30 = (23,999.92)

这里有一些经过精心修剪的代码片段。毫无疑问,SAS 很古怪。我希望有人能帮助我发现它的众多怪癖中的哪一个可能导致了这种情况。

/* CAmt and PPmt are retrieved from a lengthy PROC SQL statement, */
/* their formats are unaltered.                                   */
data WORK.TABLE1;
set WORK.TABLE0;
Difference = CAmt - PPmt;
run;

data WORK.TABLE2(keep=Rep:);
 set WORK.TABLE1 end=last;

If _N_=1 then do;
    Rep1CAmt=0;
    Rep1PPmt=0;
    Rep1Diff=0;

end;

  Rep1CAmt+CAmt;
  Rep1PPmt+PPmt;
  Rep1Diff+Difference;

if last;

Rep1Diff=Rep1CAmt-Rep1PPmt;
Rep1Diff=round(Rep1Diff,.01);

/* I realize these two lines are redundant/unnecessary, but I was trying 
   different things to get the numbers to add up correctly, no such luck */    

run;

data WORK.TABLE3;
set work.TABLE2;
AL_AMT=round(Rep1CAmt,.01);
PL_AMT=round(Rep1PPmt,.01);
DIF_AMT=AL_AMT-PL_AMT;
run;

proc append data=WORK.TABLE3 base=LIBNAME1.DB2TABLE(drop=ID) force; 
run;

最佳答案

当然,SAS 不会把直接减法搞错:

data test;
x=9918322.38;
y=9942322.30;
z=x-y;
put _all_;
run;

很可能您在早期计算中(或从 DB2 进行翻译?)遇到了一些数字精度问题。考虑以下十进制表示法:

1 - (2/3) = 0.333

0.333 + (1/3) = 0.666

0.666 + (1/3) = 0.999

二进制算术有类似但不相同的问题。在极少数情况下,当进行某些类型的数学运算时,您最终会得到类似的数字 1.0000000000000000000001423 而不是 1。因此,当您比较这两个数字或进行进一步的数学计算时,您可能不会得到您期望的答案。

为了避免这个问题,您有几个选择,所有这些都归结为使用某种形式的舍入。您可以在计算的早期点对数字进行四舍五入,这不会损害您的准确性,但可能会避免这个特定问题;您可以使用 FUZZ 函数或其兄弟之一,它是专门为此目的而设计的(如果数字在整数的 1E-12 范围内,它会返回最接近的整数 - 但如果您正在处理十进制值,您可以无法使用这个)。 ROUNDZ(模糊函数系列之一)也可能会有所帮助 - 这个示例是根据 ROUNDZ 的手册页拼凑而成的,但修改为舍入为 2.50 或 2.51,而不是 2 或 3。

data test;
format value round roundz BEST32.;
   do i=12 to 19;
      Value=2.505 - 10**(-i);
      Roundz=roundz(value,0.01);
      Round=round(value,0.01);
      output;
   end;
   do i=18 to 12 by -1;
      value=2.505 + 10**(-i);
      roundz=roundz(value,0.01);
      round=round(value,0.01);
      output;
   end;
run;

由于您使用的是 float ,我建议四舍五入到 1E-12 范围内的值 - 所以, [数字] = roundz([数字],1E-12);

这通常会消除模糊性并确保您的数字始终如一。您可能需要选择稍大的东西,例如 1E-10 - 我只非常熟悉解决整数数学案例,对于 FP 案例,我认为理论上是相同的,但并不完全有信心。

关于db2 - 两个值相减时 SAS 得到错误结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14403115/

相关文章:

sql - DB2:合并 3 列输出的函数

java - org.hibernate.hql.internal.ast.QuerySyntaxException : unexpected token: FETCH

database - 在 DB2 中为 CURRENT_TIMESTAMP 使用什么?

xml - 使用 XML 架构 (xsd) 验证输出 XML

sas - 使用 SAS 9.4 并排创建 3D 聚类条形图 2 个变量

java - PC SAS 和服务器 SAS 之间的区别

db2 - 我怎样才能让我的客户端应用程序名称显示在来自 java 的 zos 上?

database - DB2、休眠、JPA : Schema does not exist

distribution - SAS中的数据堆叠

sas - 如何将自定义拟合线添加到 SAS SGplot Scatter