文章目录
- 一. 关于“取整”
- 1. 向0取整
- 2. 向负无穷取整
- 3. 向正无穷取整
- 4. 四舍五入式的取整
- 二. 关于“取模”的本质
- 三. 取余和取模的区别
一. 关于“取整”
首先谈谈关于数学取整的问题
1. 向0取整
C中的除法和取整规则都是向0取整,即所有小数都向 0 的方向取整:
示例:
#include <stdio.h>
int main()
{
// C中的除法和取整规则都是向0取整
int i = -2.9;
int j = 2.9;
printf("%d\n", i); // -2
printf("%d\n", j); // 2
return 0;
}
补充:C++11中有一个trunc(...)
取整函数,作用就是向0取整
2. 向负无穷取整
使用 floor(...)
函数,使得所有小数都向负无穷方向取整:
示例:
#include <stdio.h>
#include <math.h> //因为使用了floor函数,需要添加该头文件
int main()
{
//本质是向-∞取整
printf("%f\n", floor(-2.9)); //-3
printf("%f\n", floor(-2.1)); //-3
printf("%f\n", floor(2.9)); //2
printf("%f\n", floor(2.1)); //2
return 0;
}
3. 向正无穷取整
使用ceil(...)
函数,使得所有小数都向正无穷方向取整:
示例:
#include <stdio.h>
#include <math.h>
int main()
{
// 本质是向+∞取整
printf("%f\n", ceil(-2.9)); //-2
printf("%f\n", ceil(-2.1)); //-2
printf("%f\n", ceil(2.9)); //3
printf("%f\n", ceil(2.1)); //3
return 0;
}
4. 四舍五入式的取整
使用round(...)
函数,可以完成对小数四舍五入式的取整:
#include <stdio.h>
#include <math.h>
int main()
{
//本质是四舍五入
printf("%f\n", round(2.1)); // 2
printf("%f\n", round(2.9)); // 3
printf("%f\n", round(-2.1));// -2
printf("%f\n", round(-2.9));// -3
return 0;
}
二. 关于“取模”的本质
取模的定义如下:
如果a和d是两个自然数,d非零,可以证明存在两个整数 q 和 r,满足 a = q*d + r ,且0 ≤ |r| < |d|。其中,q 被称为商,r 被称为余数。
下面我们对比不同语言下负数取模的结果:
可以看到,在不同语言中计算同一个表达式,负数“取模”结果是不同的。我们可以分别称之为叫做正余数 和 负余数。
由上面的例子可以看出,具体余数r的大小,本质是取决于商q的。
而商,又取决谁呢?取决于除法计算的时候,取整规则。
- Python的取整规则是向负无穷方向取整,所以先计算出来商是 -4,然后才得到余数是2
- C语言的取整规则是向0取整,所以先计算出来商是 -3,然后才得到余数是1
三. 取余和取模的区别
经过上面的例子,我们已经知道了取模(余)的本质是要先计算出商是多少,而商的值取决于商的取整规则。
所以区余和取模的区别也体现在 商的取整规则 上:
- 取余:尽可能让商,进行向0取整
- 取模:尽可能让商,向-∞方向取整
所以:
- C中%,本质其实是取余
- Python中%,本质其实是取模
关于取模和取余的一个规律
同符号数据相除,得到的商,一定是正数,即大于0!
所以在对其商进行取整的时候,向0取整和向-∞方向取整的值都一样,这样子的话:取模的值 = 取余的值。