C:负面和剩余背后的数学

时间:2013-09-14 04:51:47

标签: c math modulus

这似乎是在处理Remainder / Mod时被问到的第一件事,而且我有点碰壁。我正在教自己编写一本教科书和一堆C代码。

因为我真的没有一位教练说,“不,不。它实际上是这样的”,我以为我会在这里尝试一下。但是,我没有找到对这个数学部分的确定答案。

所以......我的印象是这种情况非常罕见,但我仍然想知道在闪亮的编译中发生了什么。另外,根据C89标准,这本教科书希望我能够提供使用负余量时可能的所有值。如果有人可以检查一下这个数学是否合理,那会不会有很多问题?

1) 9%4
9 - (2) * 4 = 1     //this is a value based on x - (x/y) * y
(2) * 4 + (1) = 9     //this is a check based on (x/y) * y + (x%y) = x

2) -9%4
9 - (2) * 4 = 1; 9 - (3) * 4 = -3   //these are the possible values
(2) * 4 + (1) = 9; (3) * 4 + (-3) = 9    //these are the checks

3) 9%-4
Same values as #2?? 

我尝试用表达式中的否定进行计算,并提出了诸如17和-33之类的荒谬事物。它们是1和-3也是#3吗?

4) -9%-4
Same as #1??

在代数分裂中,负号“取消”。他们在这里做同样的事情,还是还有其他事情发生?

我认为让我最困惑的是负面因素。我在学校(5 - 6年前)学习代数的方式,他们“依附”他们的数字。在编程中,既然它们是一元运算符,那不是这样吗?示例:在#2上填写x的值时,x = 9而不是x = -9。

我衷心感谢任何帮助。

2 个答案:

答案 0 :(得分:3)

这里你需要对余数进行数学定义。

给定两个整数 m,d ,我们说 r m 余数 >和 d 如果 r 满足两个条件:

  • 存在另一个整数 k m == k * d + r
  • 0 <= r < d

对于正数,在C中,我们只有m % d == rm / d == k,只需遵循上面的定义即可。

从定义中可以得出3%2 == 1和3/2 == 1 其他例子:

  

4/3 == 1和5/3 == 1,尽管5.0 / 3.0 == 1.6666(其中   会圆到2.0)。

     

4%3 == 1和5%3 == 2.

你也可以信任公式r = m - k * d,它在C中写成:

m % d == m - (m / d) * d

但是,在标准C中,整数除法遵循以下规则:round to 0 因此,对于负操作数,C提供的数学结果与数学结果不同 我们会:

  

( - 4)/ 3 == -1,( - 4)%3 == -1(在C中),但在简单的数学中:( - 4)/ 3 = -2,( - 4)%3 = 2。

在简单的数学中,余数总是非负的,并且小于abs(d) 在标准C中,余数始终具有第一个操作数的符号。

 +-----------------------+
 |  m  |  d  |  /  |  %  |
 +-----+-----+-----+-----+
 |  4  |  3  |  1  |  1  |
 +-----+-----+-----+-----+
 | -4  |  3  | -1  | -1  |
 +-----+-----+-----+-----+
 |  4  | -3  | -1  |  1  |
 +-----+-----+-----+-----+
 | -4  | -3  |  1  | -1  |
 +-----------------------+

备注:此描述(在否定的情况下)仅适用于标准C99 / C11。您必须小心编译器版本,并进行一些测试。

答案 1 :(得分:1)

就像Barmar的相关答案所说,数学意义上的模数意味着数字是一个环的同一类(我的代数理论有点生疏,所以抱歉这些术语可能有点松散使用:)。

因此,模数5表示您有一个大小为5的环,即0,1,2,3,4,当您添加1到4时,您将返回零。所以-9,-4,1,6,11,16都是模5,因为它们都是等价的。这对于各种代数定理实际上非常重要,但对于普通程序员来说,这几乎是无用的。

基本上标准是未指定的,因此负数返回的模数必须是那些等价数字类别之一。这不是余数。在这种情况下,最好的选择是在进行模运算时使用绝对值,如果你想要基本的整数除法。如果您使用更高级的技术(如公钥加密),您可能需要更多地学习数学。

现在我想在这种情况下仍然保持积极的态度,并且有趣的编程。