1

The number is bigger than int & long but can be accomodated in Decimal. But the normal ToString or Convert methods don't work on Decimal.

Jon Limjap
  • 94,284
  • 15
  • 101
  • 152

4 Answers4

2

Do it manually!

http://www.permadi.com/tutorial/numDecToHex/

James
  • 2,626
  • 5
  • 37
  • 51
2

I believe this will produce the right results where it returns anything, but may reject valid integers. I dare say that can be worked around with a bit of effort though... (Oh, and it will also fail for negative numbers at the moment.)

static string ConvertToHex(decimal d)
{
    int[] bits = decimal.GetBits(d);
    if (bits[3] != 0) // Sign and exponent
    {
        throw new ArgumentException();
    }
    return string.Format("{0:x8}{1:x8}{2:x8}",
        (uint)bits[2], (uint)bits[1], (uint)bits[0]);
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Well, I didn't have my handy crib-sheet to hand! It isn't just negatives - it could fail for any integer with a non-zero scale, such as 100.00M. Re thinking alike, I imagine that protocol-buffers has a lot to do with it in this case ;-p – Marc Gravell Oct 21 '08 at 09:02
  • I didn't have my crib-sheet to hand either, but I guessed until it worked :) I'll have to think about a normalize method for decimal. It shouldn't be *that* hard... – Jon Skeet Oct 21 '08 at 09:17
1

I've got to agree with James - do it manually - but don't use base-16. Use base 2^32, and print 8 hex digits at a time.

MSalters
  • 173,980
  • 10
  • 155
  • 350
1

I guess one option would be to keep taking chunks off it, and converting individual chunks? A bit of mod/division etc, converting individual fragments...

So: what hex value do you expect?

Here's two approaches... one uses the binary structure of decimal; one does it manually. In reality, you might want to have a test: if bits[3] is zero, do it the quick way, otherwise do it manually.

    decimal d = 588063595292424954445828M;
    int[] bits = decimal.GetBits(d);
    if (bits[3] != 0) throw new InvalidOperationException("Only +ve integers supported!");
    string s = Convert.ToString(bits[2], 16).PadLeft(8,'0') // high
            + Convert.ToString(bits[1], 16).PadLeft(8, '0') // middle
            + Convert.ToString(bits[0], 16).PadLeft(8, '0'); // low
    Console.WriteLine(s);

    /* or Jon's much tidier: string.Format("{0:x8}{1:x8}{2:x8}",
            (uint)bits[2], (uint)bits[1], (uint)bits[0]);  */

    const decimal chunk = (decimal)(1 << 16);
    StringBuilder sb = new StringBuilder();
    while (d > 0)
    {
        int fragment = (int) (d % chunk);
        sb.Insert(0, Convert.ToString(fragment, 16).PadLeft(4, '0'));
        d -= fragment;
        d /= chunk;
    }
    Console.WriteLine(sb);
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • I expect the value : 7c86fdcb000000000004 –  Oct 21 '08 at 08:47
  • Marc: We clearly think alike yet again, although I'd like to think my formatting code is somewhat simpler - if slower. I wonder how easy it would be to fix the "failing with some integers" problem. We really need a Normalize method in decimal :( – Jon Skeet Oct 21 '08 at 08:57
  • Normalize... well, changing the scale (via GetBits()) is easy enough - just need to check that it is an integer afterwads (or use Floor/Ceiling)... if only you had some kind of general purpose library that might host such a method... – Marc Gravell Oct 21 '08 at 09:07
  • @MarcGravell: `decimal Normalize(this decimal v) { return v/1.0000000000000000000000000000m; }` could work well – sehe Mar 03 '12 at 15:32