2

A) (Int32)X | ((Int32)Y << 16);

B) (Int32)X + (Int32)Y * (Int32)Int16.MaxValue;

Shouldn't both be equivalent? I know from testing that the first works as expected, but for some reason the second doesn't. Both X and Y are shorts (Int16), and the return type is an integer (Int32).

Shouldn't Y << 16 <=> Y * Int16.MaxValue?

4 Answers 4

6

To get the desired behaviour, you need to multiply with 0x10000 (i.e. UInt16.MaxValue+1). Int16.MaxValue is 0x7fff.

5 << 16 327680 5 * 0x10000 327680 

Compare to the decimal system: If you want to "shift" the number 5 to 500, you need to multiply with 100, not 99 :-)

Sign up to request clarification or add additional context in comments.

Comments

2

There are 2 problems with your second approach:

  • Int16 is signed, so the max value is actually only 15 bits.
  • The maximum value that can be represented by 16 bits is 2^16 - 1.

Comments

1
Right-shift 16 bits = * 2^16 

But:

Int16.MaxValue = 2^15-1 

I think that you want an unsigned 16-bit max value + 1

1 Comment

Unsigned 16-bit max value is still 2^16-1.
1

Overlooking your MaxValue being one less than a power of two, and since you have a bigger problem to cover first:

The OR and SUM operations are not similar. When you are working with 32-bit integers and 16-bit shifts, there will be carries with your + operation and bit-wise OR'ing with the OR operation.

So, the two ways are quite different.

Then, of course, the MaxValue interpretation makes your two 'shift' attempts different. It should be (x * MaxValue + x) or (x * (MaxValue+1)).

2 Comments

Since the original values are 16-bit there won't be any carry/overflow.
Ah! I seem to have overlooked the int16 reference. Then it is also likely that the compiler will use OR anyways.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.