C 具有负股息和除数的模运算差异是长无符号的
C Modulo operation differences with negative dividend and divisor is long unsigned
你好,我知道 C
负股息的 modulo
会导致负模数,但我发现负股息的模数使用长无符号除数或long long unsigned 除数会产生正模!
这是一个例子:
#include <stdio.h>
int main(int argc, char** argv)
{
long long int a = -2205348223670655684LL;
printf("%lld %lld %lld %lld %lld %lld\n", a % 20, a % 20L, a % 20LL, a % 20U, a % 20LU, a % 20LLU);
return 0;
}
和输出:
$> ./a.out
-4 -4 -4 -4 12 12
谁能解释一下为什么?我用 GCC 4.8 和 5.1
试过了
C99 第 6.5.5/6 节要求当 a/b 可表示时:
(a/b) * b + a%b shall equal a
从 6.5.5/3
The usual arithmetic conversions are performed on the operands.
算术转换的更多细节,请查看6.3.1.8小节
现在你的实现似乎是这样sizeof(long) = sizeof(long long) = 64 bits
对于前 4 种情况,有符号或无符号除数可以更改为分子类型(即 long long int
),但在后 2 种情况下,股息必须更改(转换或重新解释为)为无符号类型作为除数具有相同的宽度并且没有符号导致结果。
在某些 sizeof(long) < sizoef(long long)
的系统上,倒数第二个结果应该不同。
不存在使用一个有符号和一个无符号操作数执行的(内置)算术运算;二元运算的两个操作数都提升为相同类型。
在你最后两个例子中,那个类型是unsigned long long
;所以 a
被转换为无符号值,余数是使用它计算的。
你好,我知道 C
负股息的 modulo
会导致负模数,但我发现负股息的模数使用长无符号除数或long long unsigned 除数会产生正模!
这是一个例子:
#include <stdio.h>
int main(int argc, char** argv)
{
long long int a = -2205348223670655684LL;
printf("%lld %lld %lld %lld %lld %lld\n", a % 20, a % 20L, a % 20LL, a % 20U, a % 20LU, a % 20LLU);
return 0;
}
和输出:
$> ./a.out -4 -4 -4 -4 12 12
谁能解释一下为什么?我用 GCC 4.8 和 5.1
试过了C99 第 6.5.5/6 节要求当 a/b 可表示时:
(a/b) * b + a%b shall equal a
从 6.5.5/3
The usual arithmetic conversions are performed on the operands.
算术转换的更多细节,请查看6.3.1.8小节
现在你的实现似乎是这样sizeof(long) = sizeof(long long) = 64 bits
对于前 4 种情况,有符号或无符号除数可以更改为分子类型(即 long long int
),但在后 2 种情况下,股息必须更改(转换或重新解释为)为无符号类型作为除数具有相同的宽度并且没有符号导致结果。
在某些 sizeof(long) < sizoef(long long)
的系统上,倒数第二个结果应该不同。
不存在使用一个有符号和一个无符号操作数执行的(内置)算术运算;二元运算的两个操作数都提升为相同类型。
在你最后两个例子中,那个类型是unsigned long long
;所以 a
被转换为无符号值,余数是使用它计算的。