现在的位置: 首页 > 综合 > 正文

C除法运算时发生的截断

2014年02月21日 ⁄ 综合 ⁄ 共 826字 ⁄ 字号 评论关闭

       
C的除法往往也会隐藏着诸多陷阱,例如我们常常碰到的整数除,但是今天谈到的是关于取余运算。

        假定我们让a除以b,商为q,余数为r:

        q = a / b ;

        r = a % b ;

        在这里我们不妨假定b大于0。

        我们希望a、b、q、r之间维持怎么样的关系?

       
1. 最重要的一点,q*b+r = a要成立,余数的定义嘛

        2. 如果我们改变a的正负号,我们希望这会改变q的符号,但这不会改变q的绝对值。

        3. 当b>0时,我们希望保证r>=0且r<b。例如,如果余数用于哈希表的索引,确保它是一个有效地索引值很重要。

        上述三条性质是不是都得到满足呢?稍微举一个例子我们就能发现这个不可能同时成立。比如3/2,商为1,余数为1.此时,第一条性质得到满足。(-3)/2如果满足第2条性质的话,答案应该是商为-1,但是这样余数也为-1,这样性质3就不成立了。如果我们优先满足性质3,即余数为1,这种情况下商为-2,那么性质2不成立。

        总结:C语言在实现证书除法截断运算时,必须放弃上述三条原则中的一条。大多数程序设计语言选择放弃第3条,而改为要求余数与被除数的正负号相同

下面测试一下Visual Studio 2008编译器

#include <stdio.h>

int main()
{

	int a = -13;
	int b = 3;
	int c = a/b;
	int d = a%b;
	
	printf("a = %d\nb = %d\nc = %d\nd = %d\n",a,b,c,d);
	return 0;
}

根据性质1和性质2,同时性质3(余数的符号与被除数的符号一致),我们可以猜测出商为-4,余数为-1.

执行结果为:

我自己也总结了一下:根据性质2,我们可以在被除数与除数异号的情形下,将它们转化为绝对值进行计算,最后根据性质3,确定商与余数的符号。毕竟商的绝对值是不变的。例如,上例中可以计算13/3 = 4, 13%3 = 1,根据性质2与性质3,(-13)/3 = -4, (-13)%3 = -1。

抱歉!评论已关闭.