JAVA解惑--奇数性

   下面的方法意图确定它那唯一参数是否是一个奇数。这个方法能够正确运行吗?
public static boolean isOdd(int i){
   return i % 2 == 1;
}
   奇数可以被定义为被2整除余1的整数。表达式i % 2计算的是i整除2时所产生的余数,因此看起来这个程序应该能够正确运行。遗憾的是它不能。它在四分之一的时间里返回的都是错误的答案。
   为什么是四分之一呢?因为在所有的int数值中,有一半都是负数,而isOdd方法对于所有负奇数的判断都会失败。在任何负整数上调用该方法都会返回false,不管该整数是偶数还是奇数。
   这是Java对取余操作符的定义所产生的后果,该操作符被定义为对所有的int数值a和所有非零int数值b,都满足下面的恒等式:
   (a /b) * b + (a % b) == a
   换句话说,如果你用b整除a,将商乘以b,然后再加上余数就得到了最初的值a,该恒等式具有正确的含义,但是当与Java的截尾整数整除操作符相结合时,它就意味着:当取余操作返回一个非零的结果时,它与左操作数具有相同的正负符号。
   当i是一个负奇数时,i % 2等于-1而不是1,因此isOdd方法将错误的返回false。为了防止这种意外,读者可以自己动手测试一下。
   这个问题很好解决,只需将i % 2与0而不是与1比较,并且反转比较的含义即可:

public static boolean isOdd(int i){
   return i % 2 != 0;
}
   如果你正在在一个性能临界环境中使用isOdd方法,那么使用位操作符AND(&)来代替区域操作符会显得更好:
public static boolean isOdd(int i){
   return (i & 1) != 0;
}
   总之无论什么时候使用到了区域操作符,都要考虑到操作数和结果的符号。该操作符的行为在操作数为非负时是一目了然的。但是当一个或两个操作数都是负数时,它的行为就不那么显而易见了。

   注:该文章摘自Java解惑一书,并非原创。只是为了更多朋友学习,并且留个案例自己学习。

猜你喜欢

转载自xiaofuyan.iteye.com/blog/2353683