signed division in C

2019-06-17 08:43发布

问题:

I was reading the section on C portability in the book C Traps and Pitfalls by Andrew Koening..

On an integer divison

q = a/b;
r = a%b;

If a is a negative number, apparently the reminder r can be a negative or positive number, while satisfying the property

q * b + r == a

Normally I would expect r to be negative if dividend a is negative. And that is what I see in a intel machine with gcc. I am just curious have you ever seen a machine that would return a positive reminder when the dividend is a negative number ?

回答1:

C99 formalized the remainder as having the same sign as the dividend. Prior to C99 (C89 and K&R), it could have gone either way as both results meet the technical requirements. There are indeed compilers out there non-conforming to the C99 spec in this matter, though I don't know of any off the top of my head.

In particular, section 6.5.5 (Multiplicative operators) states:

¶5 The result of the / operator is the quotient from the division of the first operand by the second; the result of the % operator is the remainder. In both operations, if the value of the second operand is zero, the behavior is undefined.

¶6 When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded.87) If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a.

87) This is often called "truncation toward zero".

With this new definition, the remainder is basically defined as what you'd expect it to be mathematically speaking.

EDIT

To address a question in the comments, the C99 spec also specifies (footnote 240) that if the remainder is zero, on systems where zero is not signed the sign of r will be the same as that of divisor, x.

‘‘When y ≠ 0, the remainder r = x REM y is defined regardless of the rounding mode by the mathematical relation r = x − ny, where n is the integer nearest the exact value of x/y; whenever | n − x/y | = 1/2, then n is even. Thus, the remainder is always exact. If r = 0, its sign shall be that of x.’’ This definition is applicable for all implementations.