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;
答案 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
总是危险 - 即使是十进制表示中看起来“正常”的小数。
相反,您可以使用fuzz
和round
。 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;