C# 通过 IEEE 754 从浮点数转换为十六进制字符串,然后再转换回浮点数

本文关键字:浮点数 转换 字符串 然后 十六进制 通过 IEEE | 更新日期: 2023-09-27 18:35:02

我需要将float值转换为十六进制字符串并再次转换回来。在线IEEE 754转换器允许我这样做。这是我实现转换的尝试:

unsafe static void Main(string[] args)
{
    float f = 0.0023984962F;
    long l = *((long*)&f);
    float r = *((float*)&l);
    Console.WriteLine("{0} <-> {1:X} <-> {1:F1} <-> {2:F1}", f, l, r);
    Console.ReadLine();
}

我的问题:

  1. 使用浮点0.0023984962预期结果是0x3B1D3017但我的代码打印0x22CB20C3B1D3017.我做错了什么?

  2. 如何将输出保存在变量中?

C# 通过 IEEE 754 从浮点数转换为十六进制字符串,然后再转换回浮点数

为了能够两种方式进行转换,您需要两个函数。您的代码中有一个错误,您将 32 位浮点数 ( float ( 转换为 64 位整数 (long (。由于您的代码unsafe因此编译器不会捕获此错误。

但是,使用unsafe代码执行得很好,因此以下是有效的代码:

unsafe string ToHexString(float f) {
  var i = *((int*) &f);
  return "0x" + i.ToString("X8");
}
unsafe float FromHexString(string s) {
  var i = Convert.ToInt32(s, 16);
  return *((float*) &i);
}

为了避免unsafe代码的问题,您还可以使用BitConverter来检查中间字节缓冲区的大小。

string ToHexString(float f) {
  var bytes = BitConverter.GetBytes(f);
  var i = BitConverter.ToInt32(bytes, 0);
  return "0x" + i.ToString("X8");
}
float FromHexString(string s) {
  var i = Convert.ToInt32(s, 16);
  var bytes = BitConverter.GetBytes(i);
  return BitConverter.ToSingle(bytes, 0);
}

您现在可以双向转换:

var hexString = ToHexString(0.0023984962F);
var f = FromHexString(hexString);
转换

float时,您应该使用 int 而不是long,因为 float(又名 Single (是 32 位值(不像 double 是 64 位(:

unsafe static void Main(string[] args)
{
    float f = 0.0023984962F;
    int l = *((int*)&f); // int here: 32-bit float into 32-bit integer
    float r = *((float*)&l);
    // Let's save the result in the variable
    String result = String.Format("{0} <-> {1:X} <-> {1:F1} <-> {2:F1}", f, l, r);
    Console.WriteLine(result);
    Console.ReadLine();
}

但是,更好的方法是使用专门为该角色设计的BitConverter,并避免不安全的例程:

static void Main(string[] args) {
  float f = 0.0023984962F;
  uint l = BitConverter.ToUInt32(BitConverter.GetBytes(f), 0);
  float r = BitConverter.ToSingle(BitConverter.GetBytes(l), 0);
  // Let's save the result in the variable
  String result = String.Format("{0} <-> {1:X} <-> {1:F1} <-> {2:F1}", f, l, r);
  Console.WriteLine(result);
  Console.ReadLine();
}

要回答第二个问题,您可以使用字符串变量来存储输出,例如:

String output = String.Format("{0} <-> {1:X} <-> {1:F1} <-> {2:F1}", f, l, r);