计算机取余/取整
我们常常认为,C语言里,整数除法 是使用的“下取整”除法,因为:4 / 3 = 1
。
但是,-4 / 3 = -1.3333
,他的下取整 应该是-2
。但是,为什么程序输出了 -1
???
实际上,对整数的除法,对于无法除尽的情况,我们会将他转换成: (可以除尽)
、、(即,交给计算机的两个数a/ b
,其实他是可以除尽的!!)
DIV( a, b);
a = k * b + r
,即k = (a - r) / b
减去“余数r”后, (a - r)
这个数,一定是可以 被b
整除的!!
所有的除法,不管结果是多少,必须满足: a = k * b + r
而问题的关键在于:这个“余数r” 怎么求?
r = a - k*b
,这肯定是不行的,因为此时k
正是需要求的数 k
是未知的。
r = a % b
,这是求余数的算法。
比如,-4 / 3
。
-4 = -1 * 3 + -1
和 -4 = -2 * 3 + 2
这两种结果,也许你会认为是: 除法“上取整、下取整”的结果。
其实在计算机里,上下取整的结果,是要根据 “余数”来计算的。
因为:k = (a - r) / b
。 (先求出余数r,才能求出结果k)
而,C语言对 %
的定义, 是一种称为: Truncate
取余。
首先,先介绍: Truncate
取整。
就像上面看的到,在C语言里:
- 整数除法对
1.333
会取到1
(即下取整) - 整数除法对
-1.333
会取到-1
(即上取整)
所谓 Truncate(截断、去除)
,即将(小数点后的数值)直接扔掉!!!
这就导致了: (正数是 下取整 小了)(负数是 上取整大了) 即,结果会向 0
靠拢
所以,C/Java语言的 整数除法,是使用的是: Truncate除法
即k = (a - r) / b
让(k 是 Truncate
除法)成立的 前提条件,取决于: 余数r
的值!!
你会发现:
k = (a - r) / b
,因为r = a%b
,即k = (a - a%b) / b
他的结果,就是Truncate除法
所以,你去记忆 C语言里,a%b
的规则,其实是没用的。
因为,-4 % 3
,他既可以是-1,也可以是2,都是合法的。
而对%
结果的定义,他是要根据:k = (a - a%b) / b
是Truncate除法,而反推出来的!!!
所以,反推出来的结果(也即C语言对%
的定义是):
、、4%3 = 1
-4%3 = -1
4%-3 = 1
-4%-3 = -1
、、注意,这个规则,千万不要去“死记硬背”!!! 因为取余,本来就很灵活,没有一个唯一的规则