运算符(%):关于负数求模该如何求解

关于负数求模运算到底怎么求

最近有同事问到,负数到底怎么求模,结果的符号是和除数、被除数哪一个相关。因为这个问题好像以前也纠结过,但一直没有整理记录,因此特地搜索了相关资料,同时求证了在Java中求模运算的操作

对于正整数的求模运算,我们都很熟悉。但是负数如何求模,我们来探究一下,以下主要验证是在Java和C语言开发中的负数求模操作,其它如C++、Python等语言,由于环境限制,并未验证。

自然数的求模运算定义

如果a和d是两个自然数,d非零,可以证明存在两个唯一的整数 q 和 r,满足 a = qd + r 且0 ≤ r < d。其中,q 被称为商,r 被称为余数

那么对于负数这样的定义是否也适用呢?我们来假设一个例子,被除数为负数,除数为正数,求解(-8) % 5的结果。我们发现,假如按照自然数求模运算的定义,可以有这样的一个表达式:-8 = -2 * 5 + 2,根据这个表达式,2应该为(-8) % 5的结果,但实际是否这样呢。经Java测试验证,(-8) % 5结果为 -3,经C测试验证,(-8) % 5结果也为 -3。我们再到百度计算器中来计算一下该运算结果:。

语言求解余数
Java(-8) % 5-1-3
C(-8) % 5-1-3
百度计算器(-8) % 5 2

咦!和我们在Java测试中的结果不一样。那么问题就出来了...

看来我们是不能直接把自然数的求模法则用在负数的求模上。实际上,在整数范围内,自然数的求余法则并不被很多人所接受,大家大多认可的是下面的这个定义2

如果a 与d 是整数,d 非零,那么余数 r 满足这样的关系:a = qd + r , q 为整数,且0 ≤ |r| < |d|

那么这样一来,有负数的求模操作就不是我们想象中那么简单了。如(-8) % 5可以表示为:-8 = -2 * 5 + 2,也可以表示为:-8 = -1 * 5 + (-3),即 2 和 -3 都是(-8) % 5的正确结果。这种情况下,对于取模运算,可能有两个数都符合要求。我们把 2 和 -3 分别叫做正余数和负余数。通常,当除以 d 时,如果正余数为r1,负余数为r2,那么有:

r1 = r2 + d

我们再来看一种情况。求解8 % (-5)的结果,现在我们将除数换成负数,被除数换成正数。根据定义2,我们可以将8 % (-5)表示为:8 = (-2) * (-5) + (-2),也可以表示为:8 = (-1) * (-5) + 3,即 -2 和 3 都是 8 % (-5) 的结果。在Java测试验证时,结果为 3,C语言测试验证时,结果也为 3。

语言求解余数
Java8 % (-5)-13
C8 % (-5)-13
百度计算器8 % (-5) -2

可以推断,被除数与除数中其中一个数字为负数,在进行求模运算时,Java和C语言中通常会尽量让商大一些,如在8 % (-5)中,以-1为商而不是以-2为商;在(-8) % 5中,以-1为商而不是以-2为商。

那么如果被除数和除数均为负数时,求模运算是如何进行的呢?

我们来分析一下(-8) % (-5),可以表示为:-8 = 1 * (-5) + (-3)-8 = 2 * (-5) + 2,那么按照前述推断,是否2为(-8) % (-5)的结果呢,我们到Java和C中测试一下,结果如下:

语言求解余数
Java(-8) % (-5)1-3
C(-8) % (-5)1-3
百度计算器(-8) % (-5) -3

结果却出乎我们的意料,但Java、C、百度计算器中返回的结果却是一致的。

如果我们再按照定义2分析一下,被除数与除数均为正数时的情况,8 % 5可表示为:8 = 1 * 5 + 38 = 2 * 5 + (-2),我们知道,在Java、C中,8 % 5的结果为3,即商在取值是选择了较小值,与(-8) % (-5)结果为-3所对应取的商值是同一规律:尽量让商小一些

语言求解余数
Java8 % 513
C8 % 513
百度计算器8 % 5 3

总结

根据以上分析,我们有理由做出如下总结

  • 对于同号整数求模,运算原则应遵循尽量使商小
  • 对于异号整数求模,在Java、C语言中,运算原则就遵循尽量使商大
  • 11
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值