user3240428
user3240428

Reputation: 121

How to convert Hex string to Decimal

When I try this,

Decimal m = Decimal.Parse(columns[1], System.Globalization.NumberStyles.AllowHexSpecifier);

I get an ArgumentException saying this,

The number style AllowHexSpecifier is not supported on floating point data types.

and columns[1] = 4B414D000000011613C3 btw.

what am I doing wrong and how do I fix it ?

Upvotes: 2

Views: 10227

Answers (4)

Khavasi
Khavasi

Reputation: 71

This is based on the msdn example where in the Hex value will be converted to doubles. And the same values has been taken to varify the results.

        `double dnumber = 0;

        long number;
        bool result = Int64.TryParse(hexString,
                NumberStyles.HexNumber, CultureInfo.InvariantCulture,
                out number);
        dnumber=BitConverter.Int64BitsToDouble(number);

        return dnumber;`

To use this I have given sample working program, use it in a console application and check the results.

`static void Main(string[] args) { const string formatter = "{0,27:E16}";

        Console.WriteLine(string.Format(formatter, HexStringToDouble("0")));
        Console.WriteLine(string.Format(formatter, HexStringToDouble("3FF0000000000000")));
        Console.WriteLine(string.Format(formatter, HexStringToDouble("402E000000000000")));
        Console.WriteLine(string.Format(formatter, HexStringToDouble("406FE00000000000")));
        Console.WriteLine(string.Format(formatter, HexStringToDouble("41EFFFFFFFE00000")));
        Console.WriteLine(string.Format(formatter, HexStringToDouble("3F70000000000000")));
        Console.WriteLine(string.Format(formatter, HexStringToDouble("3DF0000000000000")));
        Console.WriteLine(string.Format(formatter, HexStringToDouble("0000000000000001")));
        Console.WriteLine(string.Format(formatter, HexStringToDouble("000000000000FFFF")));
        Console.WriteLine(string.Format(formatter, HexStringToDouble("0000FFFFFFFFFFFF")));
        Console.WriteLine(string.Format(formatter, HexStringToDouble("FFFFFFFFFFFFFFFF")));
        Console.WriteLine(string.Format(formatter, HexStringToDouble("FFF0000000000000")));
        Console.WriteLine(string.Format(formatter, HexStringToDouble("7FF0000000000000")));
        Console.WriteLine(string.Format(formatter, HexStringToDouble("FFEFFFFFFFFFFFFF")));
        Console.WriteLine(string.Format(formatter, HexStringToDouble("7FEFFFFFFFFFFFFF")));
        Console.WriteLine(string.Format(formatter, HexStringToDouble(long.MinValue.ToString())));
        Console.WriteLine(string.Format(formatter, HexStringToDouble(long.MaxValue.ToString())));

        Console.ReadKey();
    }

    private static double HexStringToDouble(string hexString)
    {
        double dnumber = 0;

        long number;
        bool result = Int64.TryParse(hexString,
                NumberStyles.HexNumber, CultureInfo.InvariantCulture,
                out number);
        dnumber=BitConverter.Int64BitsToDouble(number);

        return dnumber;
    }`

The output will be

enter image description here

Upvotes: 0

david.pfx
david.pfx

Reputation: 10868

You have a 20 character string representing a hexadecimal integer and you want to convert it a numeric format. 20 characters is 80 bits so it won't fit into an integer but it will fit into a Decimal. Decimal is a 128-bit floating point representation with 96 bits of mantissa. There is no built-in conversion function that can do this.

The best strategy I can think of is this.

  1. Break the string into 3 parts, starting from the right, taking 8 characters each time. The strings will be HI=4, MI=8 and LO=8 characters.
  2. Convert each sub-string into an integer using Parse and the hex specifier.
  3. Combine the parts using the Decimal ctor: Decimal(LO,MI,HI,0,0).

See http://msdn.microsoft.com/en-us/library/bb1c1a6x%28v=vs.110%29.aspx for details.

Upvotes: 2

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186668

Decimal is floating point type, like Single, Double and so you can't parse by standard means strings like

  4B414.D000000011613C3eAF // <- '.' decimal point; 'e' exponent sign  

On the other hand, Decimal is close to int128 and we don;t have that super long int. If your value is not that big (less than 2^63 which about 9.2e18) you can try something

// It's OK in your case:
// 4B414D000000011613C3 (hex) = 5422700088726126870 (dec) < 9223372036854775808 
// use long.Parse() or ulong.Parse(): int is too small
Decimal result = long.Parse(columns[1], System.Globalization.NumberStyles.HexNumber);

In case of exceeding the UInt64 you can split your value:

// to simplify the idea, I remove negative values support
String source = "4B414D000000011613C3";

String highPart = source.Remove(source.Length - 16);
String lowPart = source.Substring(source.Length - 16);

Decimal result =
  ulong.Parse(highPart, System.Globalization.NumberStyles.HexNumber);

result = result * ulong.MaxValue + ulong.Parse(lowPart,  System.Globalization.NumberStyles.HexNumber);

Upvotes: 3

ElGavilan
ElGavilan

Reputation: 6894

Decimal is a floating point type. Try using int.Parse instead.

Upvotes: 4

Related Questions