C# Float and Double Convert to Hexadecimal
前言
因MCU或uDrive在傳輸給UI時Double和Float會透過IEEE754轉成16進制傳輸,因此這邊會介紹2種方法去轉成16進制與範例程式以供參考
理論
浮點數表達式是計算機內用來表示小數的方法,由IEEE規定組成格式,並用有32 bits單精度(float)與64 bits雙精度(double)的資料型態
浮點數的表達方法主要由4個參數組成,分別是正負符號、尾數(m)、基數(n)、指數(e) :
可以看到右圖,主要Float 與Double不同地方是在尾數存取與指數位精準位數不同,這邊先以Float為範例推演給各位觀看如下圖
範例程式
Double converter to Hex
double d = 0;
byte[] arr = new byte[9];
d = Convert.ToDouble(textBox4.Text);
arr = BitConverter.GetBytes(d);
label5.Text = BitConverter.ToString(arr);
Float converter to Hex
float result;
if (textBox5.Text != null)
{
float.TryParse(textBox5.Text.ToString(), out result);
string s1 = BitConverter.ToString(BitConverter.GetBytes(result));
label7.Text = s1;
}
Hex converter to Float
string s = textBox6.Text;
byte[] arr = new byte[s.Length / 2];
for (int i = 0; i < s.Length / 2; i++)
{
arr[i] = Convert.ToByte(s.Substring(i * 2, 2), 16);
}
float f1 = BitConverter.ToSingle(arr, 0);
label8.Text = Convert.ToString(f1);
Hex converter to Double
string hex = textBox3.Text;
long dec = Convert.ToInt64(hex, 16);
var actual = BitConverter.Int64BitsToDouble(dec);
label6.Text = Convert.ToString(actual);
Doma結果
其他方法
上面為通用方法,但可以看到存取位元較多今天如果想讓存取位元較少可以參考下面範例,但有條件限制如下
* matrix format:
* size: 32 bits
* bit[0]: +/-
* bit[7:1]: integer
* bit[31:8]: decimal
* max.: 127.9999999
* min.: -127.9999999
Double converter to Hex
private static Boolean encode_matrix(double matrix, ref Byte[] outut_buf)
{
if ((matrix > MAX_NUM_MATRIX) || (matrix < MIN_NUM_MATRIX))
{
Console.WriteLine("decode_matrix: matrix data error {matrix}\n");
return false;
}
string[] str = matrix.ToString().Split('.');
UInt32 buf = 0;
Array.Clear(outut_buf, 0, outut_buf.Length);
if (str[0].IndexOf("-") == 0)
{
str[0] = str[0].Remove(0, 1);
buf |= 0x80000000;
}
buf |= (Convert.ToUInt32(str[0]) & 0x0000007F) << 24;
if (str.Length == 2)
{
if (str[1].Length < 7)
{
int length = str[1].Length;
for (int i = 0; i < (7 - length); i++)
{
str[1] = str[1].Insert(str[1].Length, "0");
}
}
buf |= Convert.ToUInt32(str[1]) & 0x00FFFFFF;
}
outut_buf = BitConverter.GetBytes(buf);
return true;
}
Hex converter to Double
private static Boolean decode_matrix(UInt32 input_buf, ref double matrix)
{
double buf = (double)(input_buf & 0x00FFFFFF);
UInt32 dec = input_buf & 0x00FFFFFF;
//String str = dec.ToString();
//int dec_count = str.Length;
if (dec != 0)
{
buf /= 10000000;
}
buf += (input_buf & 0x7F000000) >> 24;
if ((input_buf & 0x80000000) == 0x80000000)
{
buf = -(buf);
}
matrix = buf;
return true;
}
- gains format:
*
* size: 16 bits
* bit[0]: +/-
* bit[7:1]: integer
* bit[15:8]: decimal
* max.: 127.99
* min.: -127.99
PS:這邊注意限制輸入格式為XX.XX不能輸入超過小數點後第2位 EX: 1.234這樣輸入會出現資料錯誤
Float converter to Hex
private static Boolean encode_gain(float gain, ref Byte[] outut_buf)
{
if ((gain > MAX_NUM_GAIN) || (gain < MIN_NUM_GAIN))
{
Console.WriteLine("encode_gain: gain data error {coefficient}\n");
return false;
}
string[] str = gain.ToString().Split('.');
UInt16 buf = 0;
Array.Clear(outut_buf, 0, outut_buf.Length);
if (str[0].IndexOf("-") == 0)
{
str[0] = str[0].Remove(0, 1);
buf |= 0x8000;
}
buf |= (UInt16)((Convert.ToUInt32(str[0]) & 0x0000007F) << 8);
if (str.Length == 2)
{
if (str[1].Length < 2)
{
int length = str[1].Length;
for (int i = 0; i < (2 - length); i++)
{
str[1] = str[1].Insert(str[1].Length, "0");
}
}
buf |= (UInt16)(Convert.ToUInt32(str[1]) & 0x000000FF);
}
outut_buf = BitConverter.GetBytes(buf);
return true;
}
Hex converter to Float
private static Boolean decode_gain(Int16 input_buf, ref float gain)
{
float buf = (float)(input_buf & 0x00FF);
Int16 dec = (short)(input_buf & 0x00FF);
if (dec != 0)
{
buf /= 100;
}
buf += (input_buf & 0x7F00) >> 8;
if ((input_buf & 0x8000) == 0x8000)
{
buf = -(buf);
}
gain = buf;
return true;
}