C 语言和 Python 在取余操作上的异同

这篇文章主要介绍 C 语言和 Python 在取余操作上的异同。阅读本文预计需要 6 分钟。

前言

最近在重新学习 C 语言时,发现C语言和 Python 在涉及负数%取余运算时,结果有所不同,意识到自己原先的认知有问题,故总结出来,一方面是为了分享学习,另一方面也方便日后复习。

C 语言和 Python 中的取余算法

不管是C语言,还是Python,他们在取余%运算时,所使用的算法都是一样的。
算法都是:

r = a - n*(a/n)

其中,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

  1. 如果 ab 都是 int 型,则 a/b0 取整,如:11 / 4 = 2; 11 / (-4) = -2; (-11) / 4 = -2

  2. 如果 ab 中有一个是浮点数,则 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 取余运算时,ab 必须是整型,否则程序报错。测试如下:

/*
    时间: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//ba, b中存在浮点数时,取整后,小数位为0,这与 C 语言不同。
如:

  1. 11 / 4 = 2.75; 11 / (-4) = -2.75; (-11) / 4 = -2.75

  2. 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 对于 ab 的数据类型要求并没有那么严格,当 ab 是浮点数时,也能正确输出结果(尽管这与我们取余数的本意不一样),这体现了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 其中 ab 的数据必须都是整型,否则报错;而在 Python 中,ab 可以为浮点数。

后记

我从医药研究僧跨行到程序猿,转行自学路上,深感不易,走过很多弯路,也庆幸自己喜欢记笔记,把知识点进行总结,帮助自己成功实现转行。
如果感兴趣,欢迎大家关注我的微信公众号No Bug编程笔记,或者搜索NoBugNotes关注,这个公众号主要是慢慢分享和记录自己学习编程的笔记,比如:C,Python,Java等,后续也会分享自己面试以及在职场上的成长心得。
在这里插入图片描述

参考资料

  1. 负数求余,Python和C语言的不同
  2. 取余运算 C和python的区别
发布了128 篇原创文章 · 获赞 157 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/qq_27283619/article/details/104420018