正参数的余数/模运算符定义

问题描述 投票:4回答:4

我应该在要修复的程序中找到定义了mod函数的函数:

int mod(int a, int b)
{
  int i = a%b;
  if(i<0) i+=b;
  return i;
}

有人告诉我ab始终为正...

嗯? if(i<0)

参数是that

模运算的结果是一个等价类,并且可以选择该类的任何成员作为代表

并且仅作为事后考虑

...;然而,通常的代表是最小的正残基,属于该类别的最小的非负整数,即欧几里得除法的余数。但是,其他约定也是可能的。

这意味着6 % 7可以返回6(到目前为止很好),但也可以返回-1。嗯...真的吗? (让我们忽略以下事实,即所提供的实现不能处理所有情况。)

我知道在数学上模运算是这样的。但是后来有人告诉我,C %实际上“不是实现模运算符,而是实现余数”。

那么,C如何定义%运算符?

我只能在C-Draft中找到

/运算符的结果是第一个操作数除以第二; %运算符的结果是余数。在这两个操作中,如果第二个操作数为零,行为未定义。

这是否意味着6 % 7始终为6?或者也可以是-1

c division modulo integer-division
4个回答
3
投票

永远:

  • a == (a/b)*b + a%b
  • abs(a%b) < abs(b)
  • 如果ab为正,a % b为正。

C99起,

  • a/b == trunc(a/b)
  • [a%b0或符号为a

认为6 % 7可能是-1可能是由于缺少这样的事实,即始终保证ab为正,并且缺少C99中的更改。


4
投票

根据标准:

[整数相除时,/运算符的结果为舍弃任何小数部分的代数商。如果商a / b是可表示的,表达式(a/b)*b + a%b等于a。[ISO / IEC 9899:2011:6.5.5]

这意味着a的符号保留在模中。

 17 %  3  ->  2
 17 % -3  ->  2
-17 %  3  -> -2
-17 % -3  -> -2

因此,6%7不能为-1,因为提醒必须具有相同的分红符号。


2
投票

这是否意味着6%7总是6?还是也可以是-1?

根据this documention

余数

二进制运算符%产生除法的余数第一个操作数与第二个操作数之和转换)。

[...]

当通常的算术转换后的类型是整数类型时,结果是四舍五入的代数商(不是小数)实施定义的方向(直到C99)截断为零(自C99起)

因此6 / 7将是0,并且6 % 7将是6 - 0,即6

关于模运算和等价类的主张很有趣,这不是它在C(和大多数其他编程语言)中的工作方式。

此外,即使是这种情况,-8不会在相同的等效类中吗?然后if(i<0) i+=b;无法解决问题。

但是后来有人告诉我,C%实际上“没有实现模运算符,但余数“。

好点。在我链接的文档中,它称为“剩余”。


2
投票

当一个数字或另一个数字为负数时,至少有三种不同的方式定义除法和余数算法。 (有关更多详细信息,请参见this Wikipedia article-尤其是nice picture there。)

但是,如果您知道将正数除以正数,就不会有任何歧义。除法和余数的所有三个定义都表示,如果将正数除以正数,则将得到正商和正余数。

那里的三个选项中,C使用了一个称为“截断除法”的选项。但是,对于正数,这没有任何区别。 (从前,编译器是使用截断还是使用“欧几里得”分割法取决于编译器,但事情只取决于一个定义,即C标准的多个修订版。)

这是否意味着6 % 7始终为6?或者也可以是-1

是,6 % 7始终为6(在C中,并且在三个定义中的任何一个下)。

另请参见this epic, related question

© www.soinside.com 2019 - 2024. All rights reserved.