-1

I am trying to understand why BigInteger is throwing an overflow exception. I tried to visualize this by converting the BigInteger to a byte[] and iteratively incrementing the shift until I see where the exception occurs.

  • Should I be able to bit-shift >> a byte[], or is C# simply not able to?

Code causing an exception

        uint amountToShift2 = 12;
        BigInteger num = new BigInteger(-126);
        uint  compactBitsRepresentation = (uint)(num >> (int)amountToShift2);
makerofthings7
  • 60,103
  • 53
  • 215
  • 448
  • You can't bit shift a byte[], but you won't get an exception; it simply won't compile. What you are doing is bit shifting a BigInteger – Matthew Watson Mar 04 '13 at 18:05
  • where are `num` and `amountToShift2` declared? can you post a [SSCCE](sscce.org) so that we might copy and paste your code? – Sam I am says Reinstate Monica Mar 04 '13 at 18:05
  • @SamIAm - SSCE updated. That's all you need besides a reference to System.Numerics – makerofthings7 Mar 04 '13 at 18:12
  • You're talking about a right shift on a BigInteger type, not a byte[] – Peter Ritchie Mar 04 '13 at 18:26
  • @PeterRitchie The first sentence of my question refers to me troubleshooting the BigInteger. I used the `bigInt.ToByteArray()` method to do this. This question is more about Byte Arrays than Big Integer, although Jeppe Stig Nielson solved my underlying issue. Sam Asked for SSCCE so I added it, so I understand the confusion – makerofthings7 Mar 04 '13 at 18:43
  • When you bit-shift a _negative_ integer to the right, the "missing" bit positions to the left (most significant bits) are filled with `1`s. The integer is negative exactly if the left-most bit is `1`. For example, if you shift the binary number `1xyz` where `x`, `y`, and `z` are bits, one position to the right, you get `_1xy` where `_` denotes the empty posistion. Because the leftmost bit of the original number was `1`, the `_` is set to `1` as well, so the result is `11xy`. Now, decimal `-126` has just eight bits (`10000010`). So when you shift _twelve_ places to the right, all will be `1`s. – Jeppe Stig Nielsen Mar 04 '13 at 21:04
  • Filling with ones for negative numbers, or with zeros for positve numbers, is called "arithmetic shift right". On the other hand, filling with zeros in all cases is called "logical shift right". Since the `BigInteger` is a _signed_ integer type, it is natural that it uses the "arithmetic shift right", like I described in my previous comment. – Jeppe Stig Nielsen Mar 04 '13 at 21:11

3 Answers3

1

Regarding your edited question with:

uint amountToShift2 = 12;
BigInteger num = new BigInteger(-126);
uint compactBitsRepresentation = (uint)(num >> (int)amountToShift2);

The bit shift works OK and produces a BigInteger of value -1 (negative one).

But the conversion to uint throws an exception becauce -1 is outside the range of an uint. The conversion from BigInteger to uint does not "wrap around" modulo 2**32, but simply throws.

You can get around that with:

uint compactBitsRepresentation = (uint)(int)(num >> (int)amountToShift2);

which will not throw in unchecked context (which is the usual context).

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
0

There is no >> or << bit-shift operators for byte arrays in C#. You need to write code by hand to do so (pay attention to bits that fall off).

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • @PeterRitchie Are you aware that when these answers were written, the question was quite different? – Jeppe Stig Nielsen Mar 04 '13 at 18:37
  • @JeppeStigNielsen No, I was not aware; but I'm not sure how that makes a difference. If the answer doesn't reflect the question the answer should also be edited or deleted. Why make this question more confusing? – Peter Ritchie Mar 04 '13 at 18:47
  • @PeterRitchie, I'm fine with downvote, but I'm at loss on you comment "nothing to do with `byte[]`" when both title and text in the question say "Should I be able to bit-shift >> a byte[]". I agree that sample code is not exactly related to the question, but it showed what OP have trouble with and where the need for shifting arises. – Alexei Levenkov Mar 04 '13 at 20:04
0

Something tells me that the >> operator won't work with reference types like arrays, rather it works with primitive types.

your ints are actually represented by a series of bytes, so say

int i = 6;

i is represented as

00000000000000000000000000000110

the >> shifts all the bits to the right, changing it to

00000000000000000000000000000011

or 3


If you really need to shift the byte array, it shouldn't be too terribly hard to define your own method to move all the items of the array over 1 slot. It will have O(n) time complexity though.

  • operator>> applies to BigInteger. e.g. http://msdn.microsoft.com/en-us/library/system.numerics.biginteger.op_rightshift.aspx – Peter Ritchie Mar 04 '13 at 18:25
  • Note that his edited question now shows a succesful bit shift of a `BigInteger` followed by an unsuccessful cast (conversion) from `BigInteger` to `uint`. See my answer. – Jeppe Stig Nielsen Mar 04 '13 at 18:27