0

In C#, how can I convert a 64 bit ones complement number (represented as a long or ulong) to a signed two's complement long?

For reference, I'm trying to implement ULP-based double comparison using BitConverter.DoubleToInt64Bits().

Peter Ritchie
  • 35,463
  • 9
  • 80
  • 98
ChaseMedallion
  • 20,860
  • 17
  • 88
  • 152
  • I suspect your one's complement is stored as a `string`? – Nolonar Apr 04 '13 at 14:07
  • @Nolonar: it's my understanding that integral representation of a double is lexograhically ordered if treated as a ones-complement number. Thus, I would like to convert that ones-complement representation to a twos-complement value so I can work with it as a C# long – ChaseMedallion Apr 04 '13 at 14:28
  • 1
    Unfortunately, I don't know if floats or doubles are stored in one's complement, but I do know that integer (and long) are stored as two's complement, as it makes addition between positive and negative numbers much easier. In the extreme case, you could always convert a one's complement by looking if the most significant bit is `1`. If it is, you set it to `0`, invert all the bits `~` and then increment the result by one. If the most significant bit was `0`, you already have a two's complement (as both are equivalent, when positive) – Nolonar Apr 04 '13 at 14:38
  • @Nolonar: it seems like your comment contains the answer I want. Mind reposting it as an answer? – ChaseMedallion Apr 04 '13 at 15:37

1 Answers1

3

In order to convert a one's complement to a two's complement, you'll need to check whether the number is positive or negative first.
Since the positive representation of a two's complement is equivalent to that of a one's complement, you will only need to perform conversion when your one's complement is negative.

The actual conversion is done by taking the absolute value of the one's complement, flipping all bits, then incrementing the result by one.

if (myLong >> 63 != 0) // The last bit is not 0, meaning myLong is negative
{
    myLong = (myLong & (long.MaxValue >> 1)); // sets the leading bit to 0, making myLong positive
    myLong = ~myLong + 1; // flips all bits and increments by 1
}
return myLong;


// One-liner alternative
return myLong >> 63 != 0 ? (~(myLong & (long.MaxValue >> 1))) + 1 : myLong;
Nolonar
  • 5,962
  • 3
  • 36
  • 55