这篇文章主要介绍 C 语言和 Python 在取余操作上的异同。阅读本文预计需要 6 分钟。
C 语言和 Python 在取余操作上的异同
前言
最近在重新学习 C 语言时,发现C语言和 Python 在涉及负数%
取余运算时,结果有所不同,意识到自己原先的认知有问题,故总结出来,一方面是为了分享学习,另一方面也方便日后复习。
C 语言和 Python 中的取余算法
不管是C语言,还是Python,他们在取余%
运算时,所使用的算法都是一样的。
算法都是:
其中,r
表示余数,a
表示被除数,n
表示除数,并且 n
不能为0,否则会报错。
C 语言和 Python 取余 %
运算结果存在不同,是因为它们的商向 0
还是向负无穷
方向取整存在不同。其中 C语言
从C99开始规定向 0
取整,而 Python
则规定向负无穷
取整。
向 0 取整 VS 向负无穷取整
运算式 | 真实商 | 向0取整所得商 | 向负无穷取整所得商 |
---|---|---|---|
11/4 | 2.75 | 2 | 2 |
11/-4 | -2.75 | -2 | -3 |
-11/4 | -2.75 | -2 | -3 |
从上表,我们可以发现,向 0
取整,就是把商向 0
靠拢取整;向负无穷取整,就是把商向负无穷
靠拢取整。
如果商是正数,两种取整方法的结果相同;如果商是负数时,这时两种方法就会有区别。这就是 C语言
和 Python
取余有区别的原因。
C 语言中的除法和取余测试
在 C 语言中,除法是用 /
运算。对于 a/b
:
-
如果
a
和b
都是int
型,则a/b
向0
取整,如:11 / 4 = 2; 11 / (-4) = -2; (-11) / 4 = -2 -
如果
a
和b
中有一个是浮点数,则a/b
不取整,得到真实值,如:11.0 / 4 = 2.750000; 11.0 / (-4) = -2.750000; (-11.0) / 4.0 = -2.750000
C 语言测试如下:
/*
时间:2020年2月20日18:57:19
目的:
测试 C 语言中除法 '/' 和取余 '%' 运算
*/
# include <stdio.h>
int main(void)
{
printf("a/b, a 和 b 都是 int 型时:\n");
printf("11/4 = %d\n", 11/4);
printf("11/(-4) = %d\n", 11/(-4));
printf("(-11)/4 = %d\n", (-11)/4);
printf("\n");
printf("a/b, a 和 b 不全是 int 型时:\n");
printf("11.0/4 = %f\n", 11.0/4);
printf("11.0/(-4) = %f\n", 11.0/(-4));
printf("(-11.0)/4.0 = %f\n", (-11.0)/4.0);
printf("\n");
printf("11%%4 = %d\n", 11%4);
printf("11%%(-4) = %d\n", 11%(-4));
printf("(-11)%%4 = %d\n", (-11)%4);
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
a/b, a 和 b 都是 int 型时:
11/4 = 2
11/(-4) = -2
(-11)/4 = -2
a/b, a 和 b 不全是 int 型时:
11.0/4 = 2.750000
11.0/(-4) = -2.750000
(-11.0)/4.0 = -2.750000
11%4 = 3
11%(-4) = 3
(-11)%4 = -3
--------------------------
*/
这里简单说明一下:
11%4 = 11 - 4*(11/4) = 11 - 4*2 = 3*
11%(-4) = 11 - (-4)*(11/(-4)) = 11 - 4*2 = 3
(-11)%4 = (-11) - 4*((-11)/4) = (-11) + 4*2 = -3
我们可以发现,在 C 语言中,a%b
所得余数 r
的符号,取决于被除数 a
,与 被除数 a
保持一致。
此外,C 语言中, a%b
取余运算时,a
和 b
必须是整型,否则程序报错。测试如下:
/*
时间:2020年2月20日20:27:36
目的:
测试 C 语言中取余 '%' 运算对数据类型的要求
总结:
C语言中 a%b,a 和 b必须是整型
*/
# include <stdio.h>
int main(void)
{
printf("(-11.0)%%4 = %d\n", (-11.0)%4);
return 0;
}
/*
在VSCode中的输出结果是:
--------------------------
error: invalid operands to binary % (have 'double' and 'int')
printf("(-11.0)%%4 = %d\n", (-11.0)%4);
~~~~~~~^
--------------------------
*/
Python 中的除法和取余测试
在Python中:
/
:表示真除法,得到真实的商。
//
: 表示地板除法,即向负无穷取“整”,这里要注意,a//b
当a, b
中存在浮点数时,取整后,小数位为0,这与 C 语言不同。
如:
-
11 / 4 = 2.75; 11 / (-4) = -2.75; (-11) / 4 = -2.75
-
11 // 4 = 2; 11 // (-4) = -3; (-11) // 4 = -3; 11.0//4 = 2.0; 11.0//(-4) = -3.0; (-11.0)//4.0 = -3.0
Python 测试如下:
"""
时间:2020年2月20日19:42:41
目的:
测试 Python 中除法 '/' 地板除 '//' 和取余 '%' 运算
"""
def main():
print("11/4 =", 11/4)
print("11/(-4) =", 11/(-4))
print("(-11)/4 =", (-11)/4)
print("") # 空行
print("11.0/4 =", 11.0/4)
print("11.0/(-4) =", 11.0/(-4))
print("(-11.0)/4.0 =", (-11.0)/4.0)
print("") # 空行
print("11//4 =", 11//4)
print("11//(-4) =", 11//(-4))
print("(-11)//4 =", (-11)//4)
print("") # 空行
print("11.0//4 =", 11.0//4)
print("11.0//(-4) =", 11.0//(-4))
print("(-11.0)//4.0 =", (-11.0)//4.0)
print("") # 空行
print("11%4 =", 11%4)
print("11%(-4) =", 11%(-4))
print("(-11)%4 =", (-11)%4)
return None
if __name__ == '__main__':
main()
"""
在VSCode中的输出结果是:
--------------------------
11/4 = 2.75
11/(-4) = -2.75
(-11)/4 = -2.75
11.0/4 = 2.75
11.0/(-4) = -2.75
(-11.0)/4.0 = -2.75
11//4 = 2
11//(-4) = -3
(-11)//4 = -3
11.0//4 = 2.0
11.0//(-4) = -3.0
(-11.0)//4.0 = -3.0
11%4 = 3
11%(-4) = -1
(-11)%4 = 1
--------------------------
"""
这里简单说明一下 :
11%4 = 11 - 4*(11//4) = 11 - 4*2 = 3
11%(-4) = 11 - (-4)*(11//(-4)) = 11 - 4*3 = -1
(-11)%4 = (-11) - 4*((-11)//4) = (-11) + 4*3 = 1
即,在 Python 中,a%b
所得余数 r
的符号,取决于除数 b
,与除数 b
保持一致。
此外,Python 中, a%b
取余运算时,Python 对于 a
和 b
的数据类型要求并没有那么严格,当 a
和 b
是浮点数时,也能正确输出结果(尽管这与我们取余数的本意不一样),这体现了Python 相比 C 语言更加灵活和强大。
"""
时间:2020年2月20日19:42:41
目的:
测试 Python 中取余 '%' 运算对数据类型的要求
"""
def main():
print("被除数和除数均为整数时:")
print("11/4 =", 11/4)
print("11//4 =", 11//4)
print("11%4 =", 11%4)
print("被除数为负数时:")
print("(-11)/4 =", (-11)/4)
print("(-11)//4 =", (-11)//4)
print("(-11)%4 =", (-11)%4)
print("被除数为小数时:")
print("(-11.7)/4 =", (-11.7)/4)
print("(-11.7)//4 =", (-11.7)//4)
print("(-11.7)%4 =", (-11.7)%4) # -11.7 + 4*(-11//4)) = -11.7 + 12
print(-11.7 + 12) # 这里计算机没法准确计算 0.3
print("除数为小数时:")
print("(-11)/3.5 =", (-11)/3.5)
print("(-11)//3.5 =", (-11)//3.5)
print("(-11)%3.5 =", (-11)%3.5) # -11 - 3.5*(-11//3.5) = -11 + 3.5*4
print(-11 + 3.5*4)
return None
if __name__ == '__main__':
main()
"""
在VSCode中的输出结果是:
--------------------------
被除数和除数均为整数时:
11/4 = 2.75
11//4 = 2
11%4 = 3
被除数为负数时:
(-11)/4 = -2.75
(-11)//4 = -3
(-11)%4 = 1
被除数为小数时:
(-11.7)/4 = -2.925
(-11.7)//4 = -3.0
(-11.7)%4 = 0.3000000000000007
0.3000000000000007
除数为小数时:
(-11)/3.5 = -3.142857142857143
(-11)//3.5 = -4.0
(-11)%3.5 = 3.0
3.0
--------------------------
"""
小结
C 语言和 Python 在取余 %
运算上,相同点
是都遵循同样的计算法 r = a- n*(a/n) n!=0
,其中,r
表示余数,a
表示被除数,n
表示除数,并且 n
不能为0,否则会报错。
C 语言和 Python 在涉及有负数取余 %
运算时,结果可能不同的本质原因是,**C 语言中是向 0
取整,而 Python 是向负无穷取整。
在 C 语言中,a%b
所得余数 r
的符号,取决于被除数 a
,与 被除数 a
保持一致。在 Python 中,a%b
所得余数 r
的符号,取决于除数 b
,与除数 b
保持一致。
此外,在C 语言中, a%b
其中 a
和 b
的数据必须都是整型,否则报错;而在 Python 中,a
和 b
可以为浮点数。
后记
我从医药研究僧跨行到程序猿,转行自学路上,深感不易,走过很多弯路,也庆幸自己喜欢记笔记,把知识点进行总结,帮助自己成功实现转行。
如果感兴趣,欢迎大家关注我的微信公众号No Bug编程笔记
,或者搜索NoBugNotes
关注,这个公众号主要是慢慢分享和记录自己学习编程的笔记,比如:C,Python,Java等,后续也会分享自己面试以及在职场上的成长心得。