理解负数取余运算与取模操作的关系
1.圆整
就是把一个小数或者说浮点数按某种规律近似为一个它左边或右边最近的一个整数。比如:
1.向负无穷圆整
1.8->1 1.2->1 -0.4->-1 -0.7->-1
2.向零圆整
1.6->1 1.2->1 -0.4->0 -0.7->0
3.四舍五入圆整
1.6->2 1.3->1 -0.2->0 -0.7->-1
在python有一个函数为round(),有点小特别,一般情况下为:
>>> round(1.2) 1.0 >>> round(1.6) 2.0 >>> round(-0.2) -0.0 >>> round(-0.7) -1.0
好像还在在意料之中。
特例1:
#python 3 >>>round(3.5) >>>4 >>>round(2.5) >>>2
#python 2 >>> round(3.5) 4.0 >>> round(2.5) 3.0 >>>
解析:
python2中如果浮点数距离两端一样远,则保留到离0远的一边。所以round(0.5)会近似到1,而round(-0.5)会近似到-1。
python3.5中如果距离两边一样远,会保留到偶数的一边。比如round(0.5)和round(-0.5)都会保留到0,而round(1.5)会保留到2。
特例2:
#python 2 or python 3 >>> round(2.675,2) 2.67
后面的2表示要保留的小数位数,结果为什么不是2.68呢?
解析:
这跟浮点数的精度有关。我们知道在机器中浮点数不一定能精确表达,因为换算成一串1和0后可能是无限位数的,机器已经做出了截断处理。那么在机器中保存的2.675这个数字就比实际数字要小那么一点点。这一点点就导致了它离2.67要更近一点点,所以保留两位小数时就近似到了2.67。关于浮点数,并不是想象中那样简单,后面我会补充一篇相关文章。
到这里,对于python而言,我要说:
除非对精确度没什么要求,否则尽量避开用round()函数。或者选择其他方法。 1)使用math模块中的一些函数,比如math.ceiling(天花板除法)。 2)python自带整除,python2中是/,3中是//,还有div函数。 3)字符串格式化可以做截断使用,例如 "%.2f" % value(保留两位小数并变成字符串……如果还想用浮点数请披上float()的外衣)。 4)对浮点数精度要求如果很高的话,请用decimal模块。
2.取余与取模
通常情况下,我们对取余和取模混为一谈,但是这两个是不一样的。在c、 c++ 、java、 python里面都是用%表示取模或者取余的,但是我们分别用这四门语言去计算-1%3这个式子发现结果并不一样,原因是在c、 c++、 java里面%表示取余,而在python里面%表示取模。而我开头提到的那本书直接将其混为一谈,越看越气。
进行计算的两个数符号一样时,取余和取模的结果是一样的,因为符号一样时a/b总是非负数,那么a%b的结果自然也是一样的,这里不再讨论。
在进行计算的两个数符号不一样时,取余和取模的结果是不一样的,究其原因是下面公式中在计算c的时候趋向不同。
下面的式子中:c表示a/b的商的整数部分(虽然//表示取整,但用它来表示取余或者取模的商的整数部分是不合理的,此处仅仅作为一个记号使用),则r则为取余或者取模的结果。取余或者取余的不同指出就在与:c的取值不同,取余计算中c是向0取整,取模计算中c是向负无穷取整。
c=a//b; a=c*b+r;
3.实例解析
先来几道题目给大家做做吧:
#分别计算下面4式取余和取模的结果 >>> 10 % 3 >>> -10 % -3 >>> -10 % 3 >>>> 10 % -3
先睡觉了,明天补上下文
推荐阅读
-
在编程世界里,了解“除法取余”与“取模运算”的差异
-
彻底理解Java中的取模和取余运算:你掌握了吗?
-
理解Java中的模运算(mod)和取余运算(rem)的差异
-
玩转位运算:深入理解按位与(&)操作,并学习快速取模算法
-
关于求模和求余-求余: 取整除后的余数。例如: 10 MOD 4=2; -17 MOD 4=-1; -3 MOD 4=-3; 4 MOD (-3)=1; -4 MOD 3=-1 如果有a MOD b是异号,那么得出的结果符号与a相同;当然了,a MOD b就相当于a-(a DIV B ) *b的运算。例如: 13 MOD 4=13-(13 DIV 4)*4=13-12=1 求模:
-
理解负数取余运算与取模操作的关系