C语言面试易错点:负数整形的除法和取余
C语言整形的除法的结果需要取整,例如5 / 3 = 1
。C语言中的取整方式是向零取整。
取整风格共有3种:
- 向零取整。即向坐标轴0的方向,取最近的整数。
- 向上取整。也就是向+∞取整,即取不小于结果的最小整数。
- 向下取整。也就是向-∞取整,即取不大于结果的最大整数。
所以,C语言中计算-5除以3,因为实数结果约为-1.67,向零取整,得到结果为-1。
关于除法,人们常常用向右移位的方式来快速计算一个数除以2的幂的结果,例如16 / 4 = 4
就是把10000右移2位得到100,即4;9 / 4 = 2
就是把1001右移2位得到2。事实上,这种快速计算的方法,是一种向下取整的过程,所以它只适用于被除数为正数的情况。若被除数为负数,这种右移的快速计算方式就是错误的了。下面用代码来验证一下,从10到-10,分别计算他们除以4和右移2位的结果:
#include <stdio.h>
int main()
{
int i = 0;
for (i = 10; i >= -10; i--)
{
printf("%d / 4 = %d\r\n", i, i / 4);
printf("%d >> 2 = %d\r\n", i, i >> 2);
printf("\r\n");
}
getchar();
return 0;
}
程序运算结果如下图所示:
可见,当被除数为正数的时候,除以4和右移2位的结果是一样的。但是,当被除数为负数的时候,这两个结果并不一定相同。
关于负数的右移操作的解释:以-6为例,6的二进制形式是110,所以-6的补码形式是第一位符号位为1,数据位是110取反加1,得到1010。1010右移2位,得到10。取出10的符号位1,数据位是0,数据位取反加1得到10,即十进制的2。也就是十进制-6右移2位得到十进制的-2。
有了除法的基础,取余(也叫求模)操作根据公式计算就可以了。设A除以B的结果为Q,余数为R,则A = B * Q + R, R = A - B *Q
。例如求-8 % 3
,因为-8 / 3 = -2
,那么余数就是-8 - 3 * (-2) = -2
。
取余操作除了套用公式来做,还有一个快捷的经验,就是取余的结果的符号永远和被除数的符号一样。这个经验可以用下面的例子来解释:去银行借了8万块贷款,每个月还3万,还了2个月之后,还剩下2万没还,这个2万依然是欠的,所以和8万的符号相同。