两个负数相除的余数,对负数取余数的规则是,两个负数相除的余数,对负数取余数的规则叫什么

  两个负数相除的余数,对负数取余数的规则是,两个负数相除的余数,对负数取余数的规则叫什么

  不同语言中的负余数问题

  问题的出现

  偶然在leetcode上看到这样一个问题:

  给定一个32位有符号整数,整数的反数位。

  翻译成中文是:

  给定一个32位有符号整数,从低位到高位反向输出整数,例如:

  输入:1230

  返回:321

  题目很简单,有很多种实现方式。我用了大概十分钟在脑子里想到了最好的解决方案,然后用电脑做了实验:

  int reverse_num(int x,int res)

  {

  如果(!x)返回结果;

  return reverse_num(x/10,(RES * 10 x));

  }

  int main()

  {

  int val=0;

  val=reverse_num(-9870,val);

  标准输出

  }

  输出结果:

  -789

  求解!其实也可以用循环高效实现。为什么要用递归?因为递归总能写出简洁漂亮的代码(事实上,要安装X.).

  作为一种习惯,我将再次用python实现它,使用相同的代码结构:

  定义反向(x,res):

  如果x==0:

  返回资源

  反向返回(x/10,(res*10 x))

  def main():

  编号=-9870

  res=0

  val=reverse(数字,分辨率)

  打印值

  输出结果:

  RuntimeError:超过了最大递归深度

  什么****!

  我抬起颤抖的小手,移动屏幕一行行检查代码,发现没有任何问题。

  我以为大局已定,结果被极限杀了。当然,我不能就这么算了,于是我启动了调试模式。

  毕竟程序很简单,问题很快就被发现了:

  打印-987/10

  -99

  印刷-99/10

  -10

  2010年10月印刷

  -1

  印刷-1/10

  -1

  印刷-1/10

  -1

  印刷-1/10

  -1

  在这一点上,观众先生们也应该看到了问题。从上面的运行结果来看-987/10的结果实际上是-99而不是-98,-1/10的结果是-1,再次执行-1/10的结果当然是-1,递归的退出条件是x=0,导致递归无限执行,所以堆栈溢出。

  问题的解决方法

  根据资料显示,目前主流的划分方法有两种:截断划分和Floored划分。这两种方法在处理正除法时是一致的,但在处理负除法时略有不同。

  首先需要明白,对于整数的除法,这个公式是满足的:

  m=q*n r

  m是红利。

  n是除数。

  r是余数

  q是商

  m,n,q和r都是整数。

  即:

  14=3*4 2

  用4除4得3,剩下2。

  这不是标准吗?那为什么会有差异呢?

  当然,正整数的除法是没问题的,但是如果遇到负数的除法,比如

  -8/5

  有两种结果,即:

  -8=5*(-1) (-3)

  在这种情况下,商是-1,余数是-3。

  或者:

  -8=5*(-2) 2

  在这种情况下,商是-2,余数是2。

  两种划分的不同导致了上述不同语言的不同标准。

  法定标准

  官方资料显示,C89和C98标准中对此没有规定,将实现留给编译器决定。这会导致什么?就是我们常说的实践出真知。在这种情况下,你可能会得到一个错误的结果!

  不管你的编译器是用C/C标准还是python标准,你的结论都是单一标准,写出来的代码在另一个编译器下不可移植。

  想

  这就引发了一个博主的思考:有时候,在研究这类计算机问题的时候,不能只把某个平台上的实验结果作为标准答案,这是有失偏颇的。编译器工具链(脚本解释器)往往有多个版本,但单个平台无法覆盖所有编译器(脚本解释器)版本,也许我们只是选择最通用的版本,或者选择几个分歧版本中的一个。

  统一标准

  在C99标准中,明确定义了‘向零截断’,即舍入到0。在这种模式下,在负整数除法中,当商为负时,小数部分向接近0的方向四舍五入,即舍弃小数部分,而C和Java遵循C的方式,也是同样的例子:

  -8/5=-1.6

  商是-1.6,但因为是整数除法,小数部分四舍五入为0,商是-1,所以余数是-3,即:

  -8=5*(-1) (-3)

  然而,在python中,小数部分是向1的方向舍入的。例如:

  -8/5=-1.6

  商是-1.6,但因为是整数除法,小数部分四舍五入为1,商是-2,所以余数是2,也就是:

  -8=5*(-2) 2

  我们对除法在两种不同语言中的实现有了基本的了解,但事情就到此为止了吗?不要!

  以上讨论只是

  正整数/正整数

  负整数/正整数

  还有两种情况。怎么能错过他们呢?

  负整数/负整数

  正整数/负整数

  对于负整数/负整数除法,两种除法有区别吗?

  由于C99之后统一了C有符号整数除法的标准,所以我们还是可以选择在电脑上运行代码来检查。

  正整数/负整数

  代码片段c:

  int div=8/-5;

  int mod=8%-5;

  int div 1=5/-8;

  int mod1=5%-8;

  标准输出

  标准输出

  运行结果:

  8/-5=-1

  8%-5=3

  5/-8=0

  5%-8=5

  Python代码片段:

  打印“% s % d”%( 8/-5=,8/-5)

  打印“% s % d”%( 8%-5=,8%-5)

  打印“% s % d”%( 5/-8=,5/-8)

  打印“% s % d”%( 5%-8=,5%-8)

  运行结果:

  8/-5=2

  8%-5=-2

  5/-8=-1

  5%-8=-3

  以正整数/负整数为例,C/C和python的标准如上所述。当商为负时,商的小数部分被逐一四舍五入,导致不同的结果。

  负整数/负整数

  C/C代码片段:

  int div=-8/-5;

  int mod=-8%-5;

  int div 1=-5/-8;

  int mod1=-5%-8;

  标准输出

  标准输出

  运行结果:

  -8/-5=1

  -8%-5=-3

  -5/-8=0

  -5%-8=-5

  Python代码片段:

  打印“% s % d”%(-8/-5=,-8/-5)

  打印“% s % d”%(-8%-5=,-8%-5)

  打印“% s % d”%(-5/-8=,-5/-8)

  打印“% s % d”%(-5%-8=,-5%-8)

  运行结果:

  -8/-5=1

  -8%-5=-3

  -5/-8=0

  -5%-8=-5

  两种语言输出结果一样,很多盆友开始有点迷茫。不是标准不一样,小数部分四舍五入方向不一样吗?

  如果你仔细看看上面的例子,你会发现一个先决条件。当商为负时,舍入有差异。但是,如果这里的商是正的,比如-5/-8=0.625,遵循正整数的整除法则(别忘了!两种语言对正整数的处理是一致的):

  如果商为0,则:

  -5=0*(-8) (-5)

  余数是-5

  简单总结

  Python和C/C /JAVA有两个负商除法的标准。在python中,商的小数部分被四舍五入,而在C/C /JAVA中,商的小数部分被丢弃。(网上资料显示,Ruby的处理和python是一个标准。博主没测试过。有兴趣的朋友可以试试。)

  好了,关于不同语言有符号整数除法的讨论到此结束。如果朋友们对此有什么疑问,或者发现文章有什么错误,欢迎留言。

  原创博客,转载请注明出处!

  祝大家早日实现项目,bug不粘你。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: