开发者

In C, how to get calculate the negative of an unsigned quantity

In K&R ANSI C book, section A.7.4.5 (Unary Minus Operator) it is stated:

... The negative of an unsigned quantity is computed by subtracting the promoted value from the largest value of the promoted type and adding one; ...

How exactly is this calculated? Could you give a short C example?

I don't see how this could yield the negative of, say, 200u: subtracting 200 from a max value of any integral type (signed or unsigned) and adding 1 does not result in -200.

I know what the Unary minus 开发者_Python百科does - the problem is that I don't see how the result is calculated according to the description.


Unsigned values can't be negative, so -200 is not a possible result.

What it's saying is that if UINT_MAX is 65535 on your system, then the result of:

unsigned a = 200;
unsigned b = -a;
long c = -a;

will leave 65336 in both b and c.

If your system has UINT_MAX > LONG_MAX (typically because int and long are the same size), you will need to use long long for c (although note that there's not even any guarantees that that's long enough).

This detail (that the result of negating an unsigned number is another, necessarily positive, unsigned number) can result in some unexpected effects if you do not understand it. For example, in this code the first example prints "true" but the second example prints "false":

int a = 200;
unsigned b = 200;
if (-a < 100) printf("true\n"); else printf("false\n");
if (-b < 100) printf("true\n"); else printf("false\n");

(note that we are not storing the result of the negation operator anywhere - that is not the issue).


Apparently you missed the word unsigned in the description you quoted. This is the key word in this case. In C language the "negative" of an unsigned quantity is still unsigned, meaning that it is not really negative. Unsigned values can't ever be negative, by definition. They are always positive or 0. Arithmetic of unsigned values in C is modulo arithmetic or, in simple words, unsigned quantities "wrap around" when you perform arithmetical operations on them. Unary negation is not an exception. Calculating -n when n is unsigned is no different from calculating 0 - n. If n is unsigned int and its value is 200 the expected result is not -200, but rather UINT_MAX - 200 + 1, which is exactly what the quote is telling you.


It describes operations to implement modular arithmetic, i.e. it computes a value such that

a + (-a) == 0

This makes the negated unsigned number behave closely to a negated signed number.

On machines where the number representation is two's complement (such as x86), this is done by just treating the bit pattern of the unsigned number as an ordinary signed number, and using the machine's standard "negate" instruction.


Another question has touched this topic already

Example

unsigned char i = -10;
printf("%u\n",i);

Result

246


Operations on unsigned integral types use modular arithmetic. Arithmetic modulo m is much the same as regular arithmetic, except that the result is the positive remainder when divided by m, if you haven't run into it at school (for more details, see the Wikipedia article. For example, 7 - 3 modulo 10 is 4, while 3 - 7 modulo 10 is 6, since 3 - 7 is -4, and dividing it by 10 yields a quotient of -1 and a remainder of 6 (it also could be expressed with a quotient of 0 and a remainder of -4, but that's not how it works in modular arithmetic). The possible integer values modulo m are the integers from 0 to m-1, inclusive. Negative values are not possible, and -200 isn't a valid unsigned value under any circumstances.

Now, a unary minus means a negative number, which isn't a valid value modulo m. In this case, we know that it's between 0 and m-1, because we're starting with an unsigned integer. Therefore, we're looking at dividing -k by m. Since one possible value is a quotient of 0 and a remainder of -k, another possible is a quotient of -1 and remainder of m-k, so the correct answer is m-k.

Unsigned integers in C are normally described by the maximum value, not the modulus, which means that an unsigned 16-bit number would normally be described as 0 to 65535, or as having a maximum value of 65535. This is describing the values by specifying m-1 rather than m.

What the quotation you have says that the value of a negative is taken by subtracting it from m-1 and then adding 1, so -k is m - 1 - k + 1, which is m - k. The description is a little roundabout, but it specifies the correct result in terms of the pre-existing definitions.


Let's keep it simple and look at an unsigned char... 8 bits with a value range of 0-255.

What is (unsigned char)-10 and how it it calculated?

Going by the K & R statement you quote, we have:

promoted value of -10 is 10 subtracted from largest value of promoted type is 255 plus 1 = 246

so (unsigned char)-10 is actually 246. Does that make sense?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜