我想比较两个整数。一个是row
的{{1}},另一个是NSIndexPath
的{{1}}。 count
等于0,NSArray
等于2.我将它们放在row
语句中,如下所示:
count
所以根据我的数学,if
语句应该是假的,因为我正在比较if([self.selectedSetpoint row] < ([self.theCategories count]-3))
{
//Do true stuff
}
。但是,我一直认为这句话是正确的,if
内的块正在运行。我试图0 < -1
值,以确保我不只是得到错误的值。我在if
声明之前把它放在了正确位置:
NSLog
并在控制台上得到了这个:
if
为什么这种比较真的如此?我是否误解了比较整数的事情?
我在这个比较
之上的另一个if语句NSLog(@"%d",[self.selectedSetpoint row]);
NSLog(@"%d",[self.theCategories count]-3);
NSLog(@"%@",[self.selectedSetpoint row] < ([self.theCategories count]-3)?@"Yes":@"No");
哪个是2012-07-17 08:58:46.061 App[61345:11603] 0
2012-07-17 08:58:46.061 App[61345:11603] -1
2012-07-17 08:58:46.062 App[61345:11603] Yes
,它运行正常(返回[self.selectedSetpoint row]<([self.theCategories count]-2)
)。所以我觉得使用负整数存在一些问题,我没有得到。
提前谢谢。
答案 0 :(得分:6)
我怀疑问题是count
的返回是无符号整数,并且减去超过它的幅度,它会下溢并变得非常大。我已经运行了一些测试,并且我得到了与您相同的基本行为(看起来就像它的-1
一样,并且在某些上下文中它出现作为预期......但是在if()
区块的背景下,它显然正在下降。
愚蠢的问题,但幸运的是有一个简单的解决方案:在if语句中将其放置到位:
if([self.selectedSetpoint row] < ( (int)[self.theCategories count] -3 ))
{
//Do true stuff
}
答案 1 :(得分:2)
我打算提出一个替代解决方案 - 即避免使用减法,而是在等式的另一边使用加法:
if ([self.selectedSetpoint row] + 3 < [self.theCategories count])
{
//Do true stuff
}
这可以避免陷入这种类型的下溢错误,但是它留下了另一个未被触及的错误......即在这个问题的答案中提到的转换规则:What are the general rules for comparing different data types in C?
引用该问题的答案,您会看到C99规范声明:
因此,如果[self.selectedSetpoint row] + 3
的值为负值,则比较将失败...
这里的其他答案主张将(NSUInteger)转换为(NSInteger) - 但请注意,如果您的无符号值非常大,这可能会导致溢出问题。例如:
(NSInteger) -3 < (NSInteger) 4294967289 == false...
确定必须有一个简单的方法来解决这个问题,我首先提出了一个难以解决的问题......
#define SafeLT(X, Y) \
({ typeof (X) _X = (X); \
typeof (Y) _Y = (Y); \
( _X < (NSInteger) 0 ? (( _Y > 0) ? YES : _X < _Y ) : ( _Y < (NSInteger) 0 ? NO : _X < _Y));})
无论您如何混合NSUInteger和NSInteger,这都应该有效,并且将确保最多评估一次操作数(为了提高效率)。
通过证明正确性:
_X < (NSInteger) 0
评估为True,_X必须是NSInteger且&lt; 0,所以我们检查是否_Y&gt; 0.编译器将通过评估_Y的类型在此进行正确的比较。如果Y> 0然后根据定义我们返回YES。否则我们知道X和Y都是签名的并且&lt; 0,可以安全地比较它们。然而,更简单的解决方案是将类型转换为更长的有符号整数(如果您的系统有一个整数):
#define EasySafeLT(X, Y) \
({ long long _X = (X); \
long long _Y = (Y); \
( _X < _Y);})
虽然这取决于可用的较大类型,但可能并不总是可行。
答案 2 :(得分:0)
这似乎是将签名的int与未签名的int进行比较的情况。您的日志语句将抛出您的假设,因为您要求打印签名的数字。
NSLog(@"%d", -1); //Signed
-1;
NSLog(@"%u", -1); //Unsigned (tested on ios, 32 bit ints)
4294967295;
然后当你比较时:0 < 4294967295
肯定是真的。
施放@ctrahey建议应该解决你的问题:
if([self.selectedSetpoint row] < ( (int)[self.theCategories count] -3 ))
{
//Do true stuff
}
答案 3 :(得分:0)
问题是count
属性有点NSUInteger
,当你从较小的数字中减去一个较大的数字时,你得到的数字不会小于零,你会得到一个非常大的正数,它引起了奇怪的行为。
尝试这种方式,你会得到好结果:
NSLog(@"%@",(NSInteger)[self.selectedSetpoint row] < ((NSInteger)[self.theCategories count]-3)?@"Yes":@"No");