为什么C和Ruby之间的模运算符(%)的行为对于负整数是不同的?

我在这里运行一些代码。 我试过-40 % 3 。 它给了我输出2 。 当我在C中执行相同的操作时,我得到:

 int i = (-40) % 3 printf("%d", i); 

输出是

 -1 

两种语言如何在内部执行模运算?

维基说:

给定两个正数a (被除数)和n (除数), 模n (缩写为mod n)是a by n的欧几里德除数的余数。
…. an为负数时,天真定义会失效,编程语言在定义这些值方面会有所不同


现在问题是为什么-40 % 3在Ruby中是2还是换句话说它背后的数学是什么?

让我们从欧几里德分部开始,该分部指出:

给定两个整数an ,其中n ≠ 0 ,存在唯一的整数qr ,使得a = n*q + r0 ≤ r < |n| ,其中|n| 表示n的绝对值。

现在请注意商的两个定义:

1. Donald Knuth描述了浮动除法,其中商由地板函数q=floor(a/n) ,余数r
在此处输入图像描述

商( q )总是向下舍入(即使它已经是负数),余数( r )与除数的符号相同

一些实现将商定义为

q = sgn(a)floor(|a| / n) sgn是signum函数。

其余( r )与被除数( a )具有相同的符号

现在一切都取决于q

  • 如果实现符合定义1并将q定义为floor(a/n)40 % 3值为1-40 % 32 。 这就是Ruby的情况。
  • 如果实现符合定义2并将q定义为sgn(a)floor(|a| / n) ,则40 % 3值为1-40 % 3-1 。 这似乎是C和Java的情况。

在Java和C中,模运算的结果与被除数具有相同的符号,因此-1是您的示例中的结果。

在Ruby中,它与除数具有相同的符号,因此根据您的示例,+ 2将是结果。

在ruby实现中,当分子为负且分母为正时,模运算符回答的问题是,“从分子中减去的最小正数是多少,允许分母均匀分配到结果中?”

在所有实现中,当分子和分母都是正数时,正在回答的问题是,“从分子中减去的最小正数是多少,允许分母均匀分配到结果中?”

因此,您可以看到ruby实现始终回答相同的问题,即使结果首先是非直观的。