Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 负数模运算_C_Gcc_Modulo_Negative Number - Fatal编程技术网

C 负数模运算

C 负数模运算,c,gcc,modulo,negative-number,C,Gcc,Modulo,Negative Number,在C程序中,我尝试了以下操作(只是为了检查行为) 它给我的输出是gcc中的(2,-2,-2)。我每次都期待着一个积极的结果。模数可以是负的吗?有人能解释这种行为吗?模运算的结果取决于分子的符号,因此,对于y和z 这是参考资料 整数除法 本节介绍用于执行整数除法的函数。 这些函数在GNUC库中是冗余的,因为在GNUC中 “/”运算符总是向零舍入。但在另一个C 实现“/”可能会使用不同的负参数。 div和ldiv很有用,因为它们指定了如何对 商:接近零。余数的符号与 分子 C99要求当a/b可表示

在C程序中,我尝试了以下操作(只是为了检查行为)


它给我的输出是gcc中的
(2,-2,-2)
。我每次都期待着一个积极的结果。模数可以是负的吗?有人能解释这种行为吗?

模运算的结果取决于分子的符号,因此,对于yz

这是参考资料

整数除法

本节介绍用于执行整数除法的函数。 这些函数在GNUC库中是冗余的,因为在GNUC中 “/”运算符总是向零舍入。但在另一个C 实现“/”可能会使用不同的负参数。 div和ldiv很有用,因为它们指定了如何对 商:接近零。余数的符号与 分子

C99要求当
a/b
可表示时:

(a/b)*b
+
a%b
应等于
a

从逻辑上讲,这是有道理的。对吧?

让我们看看这会导致什么:


示例A.
5/-3
-1

=>
(-1)*(-3)
+
5%(-3)
=
5

只有当
5%(-3)
为2时,才会发生这种情况


例B.
(-5)/3
-1

=>
(-1)*3
+
(-5)%3
=
-5


只有当
(-5)%3
-2

时,才会发生这种情况。C中的
%
运算符不是模运算符,而是余数运算符

对于负值,模运算符和余数运算符不同

对于余数运算符,结果的符号与被除数的符号相同,而对于模运算符,结果的符号与除数相同

C将
a%b
%
操作定义为:

  a == (a / b * b) + a % b

使用
/
整数除法,截断方向为
0
。这是对
0
(而不是对负有限性)进行的截断,它将
%
定义为余数运算符而不是模运算符。

基于C99规范:
a==(a/b)*b+a%b

我们可以编写一个函数来计算
(a%b)==a-(a/b)*b

int remainder(int a, int b)
{
    return a - (a / b) * b;
}
对于模运算,我们可以使用以下函数(假设
b>0

intmod(inta,intb)
{
int r=a%b;
返回r<0?r+b:r;
}

我的结论是C中的
a%b
是余数运算,而不是模运算。

其他答案在C99或更高版本中解释过,涉及负操作数的整数除法总是向零截断

int mod(int m, float n)
{  
  return m - floor(m/n)*n;
}

请注意,在C89中,向上或向下四舍五入的结果是由实现定义的。因为在所有标准中,
(a/b)*b+a%b
等于
a
,涉及负数操作数的
%
的结果也是在C89中定义的实现。

我认为不需要检查该数字是否为负数

求正模的一个简单函数是-


编辑:假设数学中的
N>0
N+N-1是这些约定的根源,没有断言模运算会产生积极的结果

例如

1 mod 5=1,但也可以等于-4。也就是说,1/5从0得到余数1或从5得到-4。(两个因素均为5)

同样地, -1 mod 5=-1,但也可以等于4。也就是说,-1/5从0得到余数-1或从-5得到余数4。(两个因素均为5)


为了进一步阅读,请研究数学

模运算符给出余数。 c中的模运算符通常取分子的符号

  • x=5%(-3)-此处分子为正,因此结果为2
  • y=(-5)%(3)-此处分子为负数,因此结果为-2
  • z=(-5)%(-3)-此处分子为负数,因此结果为-2
  • 此外,模(余数)运算符只能用于整数类型,不能用于浮点。

    根据第6.5.5节 乘法运算符
    ,必须满足以下条件:

    (a / b) * b + a % b = a
    
    结论 余数运算结果的符号,根据 对于C99,与股息相同

    让我们看一些例子(
    除数/除数
    ):

    当只有股息为负时 当除数为负时 当除数和被除数都为负数时
    6.5.5乘法运算符 语法
  • 乘法表达式:
    • cast表达式
    • 乘法表达式*cast表达式
    • 乘法表达式/强制转换表达式
    • 乘法表达式%cast表达式
  • 约束条件
  • 每个操作数应具有算术类型。这个 %运算符的操作数应为整数类型
  • 语义学
  • 通常的算术转换是在 操作数

  • 二进制*运算符的结果是 操作数

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

  • 整数被除时,/运算符的结果 是任何分数部分的代数商 丢弃[1]。如果商
    a/b
    是可表示的, 表达式
    (a/b)*b+a%b
    应等于int modulo(int x,int N){ return (x % N + N) %N; }
  • (a / b) * b + a % b = a
    
    (-3 / 2) * 2  +  -3 % 2 = -3
    
    (-3 / 2) * 2 = -2
    
    (-3 % 2) must be -1
    
    (3 / -2) * -2  +  3 % -2 = 3
    
    (3 / -2) * -2 = 2
    
    (3 % -2) must be 1
    
    (-3 / -2) * -2  +  -3 % -2 = -3
    
    (-3 / -2) * -2 = -2
    
    (-3 % -2) must be -1
    
     // a % b
     7 %  3 -->  1  
     7 % -3 -->  1  
    -7 %  3 --> -1  
    -7 % -3 --> -1  
    
    int modulo_Euclidean(int a, int b) {
      int m = a % b;
      if (m < 0) {
        // m += (b < 0) ? -b : b; // avoid this form: it is UB when b == INT_MIN
        m = (b < 0) ? m - b : m + b;
      }
      return m;
    }
    
    modulo_Euclidean( 7,  3) -->  1  
    modulo_Euclidean( 7, -3) -->  1  
    modulo_Euclidean(-7,  3) -->  2  
    modulo_Euclidean(-7, -3) -->  2   
    
    5 % -3
    
    { 0, -2, -1 }
    
    0 => 0, 1 => -2, 2 => -1, 3 => 0, 4 => -2, 5 => -1
    
    int mod(int m, float n)
    {  
      return m - floor(m/n)*n;
    }