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

SAS:if语句条件中的逻辑问题,sas,Sas,TL;DR:为什么下面的代码不为“checkhigh”返回True 我有一个列表,我正试图从中创建一个满足某些标准的计数表。它不起作用,在故障排除过程中,我遇到了这个问题,我被难住了。两个测试用例,级别=0.7,高/低+-0.1,第二个相同,但高+0.2。第一种情况应满足if声明: 如果电平=低+0.1,电平=高-0.1,则执行该操作 但事实并非如此。当我进一步分解它时,“level=low+0.1”返回True,但“level=high-0.1”不是它应该返回的时间。我做错了什么 data e

TL;DR:为什么下面的代码不为“checkhigh”返回True

我有一个列表,我正试图从中创建一个满足某些标准的计数表。它不起作用,在故障排除过程中,我遇到了这个问题,我被难住了。两个测试用例,级别=0.7,高/低+-0.1,第二个相同,但高+0.2。第一种情况应满足if声明:

如果电平=低+0.1,电平=高-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;

您很可能会被浮点舍入问题所困扰。您操作的数字不能由机器精确表示。您可以在这里找到一个解释(对于python,但我想对于sas也是如此):


实际上,您可以使用整数而不是浮点(例如,如果所有数字都是0.1或0.01的倍数),或者定义一个小公差ε,并用(a>b-ε和a欢迎来到浮点算术的乐趣

在十进制算术中,使用固定(非无限)的小数位数,很容易显示2/3!=1-1/3和2/3+1/3!=1.除非你绕道而行。那是因为1/3不是完全可表示的;这是一个重复的小数

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

相反,您可以使用
fuzz
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;

顺便说一句-您的示例中有一个输入错误(它不会影响结果,但是)-
chechhigh
在赋值步骤中。比较数字时存在一些数字精度问题。尝试:如果四舍五入(高,.1)=四舍五入(级别+0.1,.1),则选中高=1;保留变量checkhigh。因此,从条件为真时起,checkhigh将永远为1。虽然这与浮动精度无关,但(当然)这也是正确的,值得一提的是,尽管与手头的问题无关。我假设这只是一个玩具示例,并没有完全显示OP正在做什么。