2.1.3 向-∞取整
#include <stdio.h> #include <math.h> //因为使用了floor函数,需要添加该头文件 #include <windows.h> int main() { //本质是向-∞取整,注意输出格式要不然看不到结果 printf("%.1f\n", floor(-2.9)); //-3 printf("%.1f\n", floor(-2.1)); //-3 printf("%.1f\n", floor(2.9)); //2 printf("%.1f\n", floor(2.1)); //2 system("pause"); return 0; }
2.1.4 向+∞取整
#include <stdio.h> #include <math.h> #include <windows.h> int main() { //本质是向+∞取整,注意输出格式要不然看不到结果 printf("%.1f\n", ceil(-2.9)); //-2 printf("%.1f\n", ceil(-2.1)); //-2 printf("%.1f\n", ceil(2.9)); //3 printf("%.1f\n", ceil(2.1)); //3 system("pause"); return 0; }
2.1.5 四舍五入
#include <stdio.h> #include <math.h> #include <windows.h> int main() { //本质是四舍五入 printf("%.1f\n", round(2.1)); printf("%.1f\n", round(2.9)); printf("%.1f\n", round(-2.1)); printf("%.1f\n", round(-2.9)); system("pause"); return 0; }
结论:浮点数(整数/整数),是有很多的取整方式的。
PS:C默认向0取整。
2.2 聊聊取模
取模概念:
如果 a 和 d 是两个自然数, d 非零,可以证明存在两个唯一的整数 q 和 r ,满足 a = q * d + r 且 0 ≤ r < d 。其中, q被称为商,r 被称为余数。
我们平时都是用的正数的取模,所以并没有发现什么问题,但是想一想,我们如果遇到负数的取模呢?
1
#include <stdio.h> #include <windows.h> int main () { int a = 10 ; int d = 3 ; printf ( "%d\n" , a % d ); // 结果是 1 // 因为: a=10,d=3,q=3,r=1 0<=r<d(3) // 所以: a = q*d+r -> 10=3*3+1 system ( "pause" ); return 0 ; }
2
#include <stdio.h> #include <windows.h> int main () { int a = - 10 ; int d = 3 ; //printf("%d\n", a/d); //C 语言中是 -3 ,很好理解 printf ( "%d\n" , a % d ); system ( "pause" ); return 0 ; }
但是2在python中我们发现是2?
结论:很显然,上面关于取模的定义,并不能满足语言上的取模运算
因为在 C 中,现在 - 10 % 3 出现了负数,根据定义:满足 a = q * d + r 且 0 ≤ r < d , C 语言中的余数,是不满足定义的, 因为,r < 0 了。
故,大家对取模有了一个修订版的定义:
如果 a 和 d 是两个自然数, d 非零,可以证明存在两个唯一的整数 q 和 r ,满足 a = q * d + r , q 为整数,且 0 ≤ | r | < | d | 。其中, q 被称为商, r 被称为余数。
有了这个新的定义,那么 C 中或者 Python 中的 “ 取模 ” ,就都能解释了。
解释 C : - 10 = ( - 3 ) * 3 + ( - 1 )
解释 Python : - 10 = ( ? ) * 3 + 2 , 其中,可以推到出来 , '?' 必须是-4 ( 后面验证 ). 即 - 10 = (
- 4 ) * 3 + 2 ,才能满足定义。
所以,在不同语言,同一个计算表达式,负数 “ 取模 ” 结果是不同的。我们可以称之为分别叫做正余数 和 负余数
2.2.2 是什么决定了这种现象
由上面的例子可以看出,具体余数r的大小,本质是取决于商q的。
而商,又取决谁呢?取决于除法计算的时候,取整规则。
简单说,要先算商,再算余数,而商的取法前面说了4种,这就要看编译器。
2.2.3 取余和取模一样吗?
这两个并不能严格等价 ( 虽然大部分情况差不多 ) 取余或者取模,都应该要算出商,然后才能得出余数。
本质 1 取整:
取余:尽可能让商,进行向0取整。
取模:尽可能让商,向-∞方向取整。
故:
C中%,本质其实是取余。
Python 中 % ,本质其实是取模。
理解链:
对任何一个大于 0 的数, 对其进行0向取整和-∞取整 ,取整方向是一致的。故取模等价于取余
对任何一个小于 0 的数, 对其进行0向取整和-∞取整 ,取整方向是相反的。故取模不等价于取余
同符号数据相除,得到的商,一定是正数(正数 vs 正整数),即大于 0 !
故,在对其商进行取整的时候,取模等价于取余。
本质 2 符号:
参与取余的两个数据,如果同符号,取模等价于取余
2.2.4 如果参与运算的数据,不同符号呢?
#include <stdio.h> #include <windows.h> int main() { printf("%d\n", -10 / 3); //结果:-3 printf("%d\n\n", -10 % 3); //结果:-1 为什么? -10=(-3)*3+(-1) printf("%d\n", 10 / -3); //结果:-3 printf("%d\n\n", 10 % -3); //结果:1 为什么?10=(-3)*(-3)+1 system("pause"); return 0; }
明显结论:如果不同符号,余数的求法,参考之前定义。而余数符号,与被除数相同(?)。
但是:
好像不是这样的,为什么呢?
重新看看定义:
如果 a 和 d 是两个自然数, d 非零,可以证明存在两个唯一的整数 q 和 r ,满足 a = q * d + r , q 为整数,且 0 ≤ | r | < | d | 。其中, q 被称为商, r 被称为余数。
a = q * d + r 变换成 r = a - q * d 变换成 r = a + ( - q * d )
对于: x = y + z ,这样的表达式, x 的符号 与 | y | 、 | z | 中大的数据一致。
而 r = a + ( - q * d ) 中, | a | 和 |- q * d | 的绝对值谁大,取决于商 q 的取整方式。
c 是向 0 取整的,也就是 q 本身的绝对值是减小的。
如:
- 10 / 3 =- 3.333 . 33 向 0 取整 - 3. a =- 10 | 10 | , - q * d =- ( - 3 ) * 3 = 9 | 9 |
10 /- 3 =- 3.333 . 33 向 0 取整 - 3. a = 10 | 10 | , - q * d =- ( - 3 ) * ( - 3 ) =- 9 | 9 |
绝对值都变小了
python 是向 - ∞ 取整的,也就是 q 本身的绝对值是增大的。
- 10 / 3 =- 3.333 . 33 '//' 向 - ∞ 取整 - 4. a =- 10 | 10 | , - q * d =- ( - 4 ) * 3 = 12 | 12 |
10 /- 3 =-- 3.333 . 33 '//' 向 - ∞ 取整 - 4. a = 10 | 10 | , - q * d =- ( - 4 ) * ( - 3 ) =- 12 | 12 |
绝对值都变大了
结论:如果参与取余的两个数据符号不同,在 C 语言中 ( 或者其他采用向 0 取整的语言如: C ++ , Java ) ,余数符号,与被除数相同。
2.2.5 总结
浮点数(或者整数相除),是有很多的取整方式的。
如果a和d是两个自然数,d非零,可以证明存在两个唯一的整数 q 和 r,满足 a = q*d + r , q 为整数,且0 ≤ |r| < |d|。其中,q 被称为商,r 被称为余数。
在不同语言,同一个计算表达式,“取模”结果是不同的。我们可以称之为分别叫做正余数 和 负余数。
具体余数r的大小,本质是取决于商q的。而商,又取决于除法计算的时候,取整规则。
取余vs取模: 取余尽可能让商,进行向0取整。取模尽可能让商,向-∞方向取整。
参与取余的两个数据,如果同符号,取模等价于取余。
如果参与取余的两个数据符号不同,在C语言中(或者其他采用向0取整的语言如:C++,Java),余数符号,与被除数相同。(因为采用的向0取整)
今天的内容就到这里了哈!!!
要是认为作者有一点帮助你的话!
就来一个点赞加关注吧!!!当然订阅是更是求之不得!
最后的最后谢谢大家的观看!!!
你们的支持是作者写作的最大动力!!!
下期见哈!!!