问题
int x = random();
int y = random();
unsigned ux = (unsigned) x;
unsigned uy = (unsigned) y;
For each of the following C expressions, you are to indicate whether or not the expression always yields 1. If it always yields 1, describe the underlying mathematical principles. Otherwise, give an example of arguments that make it yield 0.
A. (x<y) == (-x>-y)
B. ((x+y)<<4) + y-x == 17*y+15*x
C. ~x+~y+1 == ~(x+y)
D. (ux-uy) == -(unsigned)(y-x)
E. ((x >> 2) << 2) <= x
For these questions, I got that only A could yield 0 while the rest always yielded 1.
I know this is probably wrong and I'm not looking for direct answers but I was hoping to get some general knowledge / advice on how to approach these problems.
I have a really bad professor and I've been trying to find resources online but I don't really know where to start or what to look for. I know the basics of unsigned / two's complement arithmetic and bit-shifting but I don't know how to apply it to find counter cases for these problems.
回答1:
The C programming language does not specify the result of an overflow of integral signed quantities; neither it defines x << n
if x
is signed and negative.
However, it is not uncommon that arithmetic operations are performed regardless of the sign, considering both signed and unsigned n-bit integers to be numbers modulo 2^n represented in the two's complement system.
This must be assumed for your exercise, which is almost meaningless otherwise.
Example for 8-bit integers:
unsigned domain: (0..127), ( 128..255)
signed domain: (0..127), (-128..-1)
in binary representation:
unsigned domain: 00000000..01111111 and 10000000..11111111
signed domain: 00000000..01111111 and 10000000..11111111
Between signed and unsigned, only the representative system of the integers
modulo 2^n differ, which is relevant for printing, but not for internal
computations (as long as only +
, -
, *
and bitwise operations are used).
For signed integers, exactly the negative integers have the first bit set to 1. Casts between signed and unsigned are irrelevant except for printing.
I insist, this is assumed for your exercises, but the C programming language does not specifies most of my claims.
A. (x<y) == (-x>-y)
Is disproved by x == INT_MIN
, y == INT_MIN + 1
,
because INT_MIN == -INT_MIN
.
B. ((x+y)<<4) + y-x == 17*y+15*x
True:
((x+y) << 4 ) + y-x
== ((x+y) * 0x10000) + y-x
== ((x+y) * 16 ) + y-x
== 17 * y + 15 * x
C. ~x+~y+1 == ~(x+y)
True:
x + ~x + 1 == 0
~x + 1 == -x
~(x+y) + 1 == -(x+y)
~(x+y) + 1 == -x + -y
~(x+y) + 1 == ~x + 1 + ~y + 1
~(x+y) == ~x + ~y + 1
D. ((unsigned)x-(unsigned)y) == -(unsigned)(y-x)
True: the cast from signed to unsigned is assumed not to change the internal
representation, and operators are assumed to ignore the signedness of
integers. In other words, x-y == -(y-x)
holds wherever casts are put.
E. ((x >> 2) << 2) <= x
True:
x
== (x >> 2) << 2 + two_last_significant_bits_of_x
== (x >> 2) << 2 + positive
>= (x >> 2) << 2
Examples with signed 32-bit integers:
x == 5
x == 00000000000000000000000000000101 in base2
x >> 2 == 00000000000000000000000000000001 in base2
(x >> 2) << 2 == 00000000000000000000000000000100 in base2
(x >> 2) << 2 == 4
x == -5
x == 11111111111111111111111111111011 in base2
x >> 2 == 11111111111111111111111111111110 in base2
(x >> 2) << 2 == 11111111111111111111111111111000 in base2
(x >> 2) << 2 == -8
来源:https://stackoverflow.com/questions/29572107/unsigned-signed-arithmetic-problems-from-a-programmers-perspective-textbook