C/C++取模运算
今天看 《C++ Primer》 时,产生了一些疑问,经过一番研究,弄明白了C++中取模和取余,记录在这里。
原因是读到了第二章的这段:
当赋给无符号类型一个超出它范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数。
例如,8比特大小的unsigned char可以表示0至255区间的值,如果赋了一个区间外的值,比如把 -1赋给unsigned char,则实际的结果是255。
取模和取余运算过程是相似的,废话不多说,直接上代码:
#include <iostream>
#include <cmath>
int main ()
{
std::cout << (-1) % 256 << std::endl;
unsigned char i;
i = -1;
int b = i;//直接输出i会给出一个char类型的字符而不是数字
std::cout << b << std::endl;
int c = -1;
double d = 256,e = 0,f = 0,g = 0,h = 0;
e = floor(c / d);
f = -1 - (e * d);
std::cout << f << std::endl;
g = ceil(c / d);
h = -1 - (g * d);
std::cout << h << std::endl;
}
输出结果如下:
-1
255
255
-1
分析:第一个输出是直接使用 % 取余,得到 -1;第二个是测试C++隐含的转换,得到255;第三个是分步取模,第四个是分步取余。
取模和取余本质上的区别在于,取模时,需要将商(e)先转换(floor)为不大于商本身的最小数(可为负)进行计算,而取余时需要将商(g)先转换(ceil)为向接近于0的下一个整数再进行计算。
其中floor和ceil函数在cmath(math.h) 中定义。
由此可见,C++中 % 是取余运算符而不是取模运算符。
2020.10.02补充:
C++ Pimer第125页写道,C++早期版本没有规定 % 是取模还是取余,而C++11明确规定了 % 在运算过程中需要对商向0取整,所以C++的 % 是取余运算,这也造成了网络上很多关于这点的错误描述。
2022.01.30补充:
陈硕在带符号整数的除法与余数中提到,C99规定了向零取整。