SAS:if语句条件中的逻辑问题

时间:2016-01-14 15:07:42

标签: sas

TL; DR:为什么下面的代码没有为'checkhigh'返回True?

我有一个列表,我试图创建一个满足特定条件的计数表。它没有工作,在排除故障时我遇到了这个问题而且我很难过。两个测试用例,level = 0.7,高/低+ -0.1,第二个相同,但高+0.2。第一种情况应该满足if语句:

如果level = low + 0.1且level = high-0.1则执行;

但事实并非如此。当我进一步分解时,“level = low + 0.1”返回True,但“level = high-0.1”不是应该的时候。我做错了什么?

data ex1; 
  input id $ level $ high $ low;
  cards; 
t1 0.7 0.8 0.6
t2 0.7 0.9 0.6
; 
run; 

data table1; 
    set ex1 (keep= id level high low);
retain
checklow 0
checkhigh 0
;

if level = 0.7 then do;
    lowcheck = low+0.1;
    highcheck = high-0.1;
    if level = low + 0.1 then checklow = 1;
    if  high = level + 0.1 then chechhigh = 1;
    if level = low+0.1 and level=high-0.1 then do; ahhhh = 1; count = count+1;end;

end;
run;

2 个答案:

答案 0 :(得分:0)

您很可能会遇到浮点舍入问题。您操作的数字无法由机器精确表示。你可以在那里找到解释(对于python,但我认为对于sas来说是相同的): https://docs.python.org/2/tutorial/floatingpoint.html

在实践中,您可以使用整数而不是浮点(例如,如果您的所有数字都是0.1或0.01的倍数),或者定义一个小的容差epsilon,并用(a>)替换a = b的测试。 b - epsilon和< b + epsilon)。

答案 1 :(得分:0)

欢迎来到浮点运算的乐趣。

在十进制算术中,使用固定(非无限)小数位数,显示2/3!= 1-1 / 3和2/3 + 1/3!= 1是微不足道的,除非你回合。那是因为1/3不能完全代表;这是一个重复的小数。

在二进制算术中,同样不可能完全表示1/10。 (事实上​​,只有2的负幂是; 1 / 3,1 / 5,1 / 10等都不可能完全代表。)因此,你有不精确匹配的风险。在浮点运算中,使用小数时equals 总是危险 - 即使是十进制表示中看起来“正常”的小数。

相反,您可以使用fuzzroundfuzz消除了与整数之间的微不足道的差异(但如果你的比较是两个非整数则不起作用);当然,round会缩小到一个较小的点,即使非整数也应该消除微不足道的差异。

在您的情况下,round是可行的方法:

data table1; 
    set ex1 (keep= id level high low);
retain
checklow 0
checkhigh 0
;

if level = 0.7 then do;
    lowcheck = low+0.1;
    highcheck = high-0.1;
    if level = round(low + 0.1,.1) then checklow = 1;
    if  level = round(high - 0.1,.1) then checkhigh = 1;
    if level = low+0.1 and level=high-0.1 then do; ahhhh = 1; count = count+1;end;
  put level= low= high= checklow= checkhigh=;
end;
run;