[C#.NET] 浮點數 轉 Hexadecimal

  • 10245
  • 0
  • C#
  • 2016-07-11

[C#.NET] 浮點數 轉 Hexadecimal

由於設備商所定義的通訊協定裡會用到浮點數,所以我就利用下列方式將浮點數轉成16進制的字串格式
用 BitConverter 轉成 16 進制的字串
public void FloatToHexStringTest()
{
    var expected = "4200CCCD";

    float source = 32.2f;
    byte[] sourceArray = BitConverter.GetBytes(source);
    var number = BitConverter.ToUInt32(sourceArray, 0);
    string actual = number.ToString("X");
    Assert.AreEqual(expected, actual);
}

 
字串反轉成浮點數
public void HexStringToFloatTest()
{
    var expected = 32.2f;

    string source = "4200CCCD";
    var number = int.Parse(source, System.Globalization.NumberStyles.AllowHexSpecifier);
    byte[] numberArray = BitConverter.GetBytes(number);
    float actual = BitConverter.ToSingle(numberArray, 0);
    Assert.AreEqual(expected, actual);
}

 
或是使用 DoubleToInt64Bits 來轉成16進制的字串
public void FloatToHexStringTest1()
{
    var expected = "40401999A0000000";
    float source = 32.2f;
    long number = BitConverter.DoubleToInt64Bits(source);
    var actual = number.ToString("X");
    Assert.AreEqual(expected, actual);
}

 
用 Int64BitsToDouble 反轉回浮點數
public void HexStringToFloatTest1()
{
    float expected = 32.2f;
    string hex = "40401999A0000000";
    long dec = Convert.ToInt64(hex, 16);
    var actual = BitConverter.Int64BitsToDouble(dec);
    Assert.AreEqual(expected, actual);
}
但是設備商給我的格式只有兩個 byte ,上列的方式至少要有4個 byte,於是經我詢問的結果,設備商的做法是整數擺一個byte,
小數擺一個byte(小數只取後兩位),所以我又將程式碼改成以下:
這段程式碼的原理很簡單,只是把小數跟整數拆開放在不同的byte,這個測試方法裡有用到無條件捨去小數點後兩位,如果不想那麼那麼麻煩,
也可以利用double.ToString(“F2”)來處理,不過這樣的做法會進位,
可參考:http://stackoverflow.com/questions/4916240/format-double-in-c-sharp
public void DoubleToHexStringTest1()
{
    double source = 32.22677921;

    //無條件捨去小數點後兩位
    double pow = Math.Pow(10, 2);
    double sign = source >= 0 ? 1 : -1;
    source = sign * Math.Floor(sign * source * pow) / pow;

    var inputString = source.ToString();
    var index = inputString.IndexOf(".");

    var hi = "";
    var lo = "";
    if (index > 0)
    {
        //有小數
        var split = inputString.Split('.');
        hi = (byte.Parse(split[0])).ToString("X").PadLeft(2, '0');
        lo = (byte.Parse(split[1])).ToString("X").PadLeft(2, '0');
    }
    else //沒有小數
    {
        hi = (byte.Parse(inputString)).ToString("X").PadLeft(2, '0');
        lo = 0.ToString("X").PadLeft(2, '0');
    }
    var expected = "2016";
    var actual = hi + lo;
    Assert.AreEqual(expected, actual);
}

 
字串反轉成浮點數
public void HexStringToDoubleTest1()
{
    double expected = 32.22;
    var source = "2016";
    var sourceArray = Enumerable.Range(0, source.Length)
                     .Where(x => x % 2 == 0)
                     .Select(x => Convert.ToByte(source.Substring(x, 2), 16))
                     .ToArray();

    var temp = sourceArray[0] + "." + sourceArray[1];
    var actual = double.Parse(temp);
    Assert.AreEqual(expected, actual);
}

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo