4.2.2 整数运算和一元负号运算符
代码清单4-3巩固了前面讨论的内容,并引入了整数运算的概念。
代码清单4-3
//More arithmetic expressions
import<Foundation/Foundation.h>
int main(int argc, char*argv[])
{
NSAutoreleasePool*pool=[[NSAutoreleasePool alloc]init];
int a=25;
int b=2;
int result;
float c=25.0;
float d=2.0;
NSLog(@“6+a/5b=%i”,6+a/5b);
NSLog(@“a/bb=%i”,a/bb);
NSLog(@“c/dd=%f”,c/dd);
NSLog(@“a=%i”,-a);
[pool drain];
return 0;
}
代码清单4-3输出
6+a/5*b=16
a/b*b=24
c/d*d=25.000000
-a=-25
前三条语句中,在int和a、b及result的声明之间插入了额外的空格,以便对齐每个变量的声明。使用这种方法书写语句可使程序更容易阅读。还可以注意到,在迄今出现的每个程序中,每个运算符前后都有空格。这种做法同样不是必需的,仅仅是出于美观上的考虑。一般来说,在允许单个空格的任何位置都可以插入额外的空格。如果能使程序更容易阅读,敲击空格键的操作还是值得做的。
在代码清单4-3中,第一个NSLog调用中的表达式巩固了运算符优先级的概念。该表达式的计算按以下顺序执行:
1.因为除法的优先级比加法高,所以先将a的值(25)除以5。该运算将给出中间结果4。
2.因为乘法的优先级也大于加法,所以随后中间结果(5)将乘以2(即b的值),并获得新的中间结果(10)。
3.最后,计算6加10,并得出最终结果(16)。
第二条NSLog语句引入了一个新误区。你希望a除以b再乘以b的操作返回a(已经设置为25)。但此操作并不会产生这一结果,在输出显示器上显示的是24。难道计算机在某个地方迷失了方向?如果这样就太不幸了。其实该问题的实际情况是:这个表达式是采用整数运算来求值的。
如果回头看一下变量a和b的声明,你会想起它们都是用int类型声明的。当包含两个整数的表达式求值时,Objective-C系统都将使用整数运算来执行这个操作。在这种情况下,数字的所有小数部分将丢失。因此,计算a除以b,即25除以2时,得到的中间结果是12而不是期望的12.5。这个中间结果乘以2就得到最终结果24,这样,就解释了出现“丢失”数字的情况。
在代码清单4-3的倒数第二个NSLog语句中看到,如果用浮点值代替整数来执行同样的运算,就会获得期望的结果。
决定使用float变量还是int变量应该基于变量的使用目的。如果无需使用任何小数位,可使用整型变量。这将使程序更加高效,换言之,它可以在大多数计算机上更加快速地执行。另一方面,如果需要精确到小数位,很清楚应该选择什么。此时,唯一必须回答的问题是使用float还是double。对此问题的回答取决于使用数据所需的精度以及它们的量级。
在最后一条NSLog语句中,使用了一元负号运算符对变量a的值求反。这个一元运算符是用于单个值的运算符,而二元运算符作用于两个值。负号实际上扮演了一个双重角色:作为二元运算符,它执行两个数相减的操作;作为一元运算符,它对一个值求反。
与其他算术运算符相比,一元负号运算符具有更高的优先级,但一元正号运算符(+)除外,它和算术运算符的优先级相同。因此,表达式
c=-a*b;
将执行-a乘以b。再次参见附录B,其中有一个包括各种运算符及其优先级的总结表。