如何将字节值转换为十进制数?

6

我正在尝试从文件中加载一些十进制值,但我无法找到正确的方法将原始值转换为十进制。

我已经将文件读入字节数组中,每个四个字节的块应该表示一个十进制值。为了帮助理解,我构建了一个表格,显示了十进制值1到46如何表示为四个字节的块。

例如,数字1显示为0,0,128,63,数字2显示为0,0,0,64,依此类推,直到46,即0,0,56,66。完整的表格可以在这里找到。

还有另一系列包括负数的三位小数的数字,可以在这里找到。

我唯一的文档说明如下:

它们以最不重要的字节为首:1、256、65536、16777216。这使得十六进制序列01 01 00 00变成了257(十进制)。在C/C++中,要读取例如float,请执行以下操作:float x; fread(&x, sizeof(float), 1, fileptr)。但是我正在使用.NET的File.ReadAllBytes方法,所以这没有什么帮助。如果有人能抽出几分钟时间查看示例文件并看看是否可以找到将值转换为十进制的方法,我将不胜感激。
4个回答

3

您是否考虑过使用 BitConverter 类?它可以在字节数组和各种类型之间进行转换。

编辑: MSDN 在 http://msdn.microsoft.com/en-us/library/system.bitconverter_methods(v=vs.85).aspx 上对 BitConverter 的文档提供了一个有用的评论:

public static decimal ToDecimal(byte[] bytes)
{
  int[] bits = new int[4];
  bits[0] = ((bytes[0] | (bytes[1] << 8)) | (bytes[2] << 0x10)) | (bytes[3] << 0x18); //lo
  bits[1] = ((bytes[4] | (bytes[5] << 8)) | (bytes[6] << 0x10)) | (bytes[7] << 0x18); //mid
  bits[2] = ((bytes[8] | (bytes[9] << 8)) | (bytes[10] << 0x10)) | (bytes[11] << 0x18); //hi
  bits[3] = ((bytes[12] | (bytes[13] << 8)) | (bytes[14] << 0x10)) | (bytes[15] << 0x18); //flags

  return new decimal(bits);
}

public static byte[] GetBytes(decimal d)
{
  byte[] bytes = new byte[16];

  int[] bits = decimal.GetBits(d);
  int lo = bits[0];
  int mid = bits[1];
  int hi = bits[2];
  int flags = bits[3];

  bytes[0] = (byte)lo;
  bytes[1] = (byte)(lo >> 8);
  bytes[2] = (byte)(lo >> 0x10);
  bytes[3] = (byte)(lo >> 0x18);
  bytes[4] = (byte)mid;
  bytes[5] = (byte)(mid >> 8);
  bytes[6] = (byte)(mid >> 0x10);
  bytes[7] = (byte)(mid >> 0x18);
  bytes[8] = (byte)hi;
  bytes[9] = (byte)(hi >> 8);
  bytes[10] = (byte)(hi >> 0x10);
  bytes[11] = (byte)(hi >> 0x18);
  bytes[12] = (byte)flags;
  bytes[13] = (byte)(flags >> 8);
  bytes[14] = (byte)(flags >> 0x10);
  bytes[15] = (byte)(flags >> 0x18);

  return bytes;
}

谢谢,这绝对是正确的方式。 - gilles27
很遗憾,它没有实现十进制转换。 - Eran Betzalel
@EranBetzalel MSDN上有一些代码可以实现BitConverter的“缺失”成员。请查看我的编辑更新。 - BlueMonkMN
@BlueMonkMN,这不是MSDN的,只是一些人在那里发布了它,他可能从我获取信息的同一个地方获取了它 - .Net反编译库。这与BitConvertor无关。 - Eran Betzalel
@EranBetzalel 我的观点是,这是MSDN网站包含内容和BitConverter页面上可以找到内容。我并不声称它与MSDN或bitconverter本质上有关联(我甚至指出这是一条“评论”)。但是,解决方案是解决方案,无论谁编写它或在哪里。现在,解决方案在StackOverflow上。由你作为编码人员来判断代码是否适合你,而不是根据其来源的凭据来确定。代码可以独立地根据其自身的优点进行评估。 - BlueMonkMN

3

您可以使用BitConverter.ToSingle从字节数组中读取浮点值,因此要获取一系列浮点数,您可以像这样进行操作:

byte[] data = File.ReadAllBytes(fileName);
int count = data.Length / 4;
Debug.Assert(data.Length % 4 == 0);

IEnumerable<float> values = Enumerable.Range(0, count)
    .Select(i => BitConverter.ToSingle(data, i*4));

我已将此标记为正确,因为它稍微更详细。非常感谢,没想到这么简单。 - gilles27

1

.NET库内部实现了Decimal.GetBytes()方法。

我使用反编译的.NET库创建了一个简单的十进制和字节数组之间的转换方法 - 您可以在这里找到它:

https://gist.github.com/eranbetzalel/5384006#file-decimalbytesconvertor-cs

编辑:这是来自我的链接的完整源代码。

public decimal BytesToDecimal(byte[] buffer, int offset = 0)
{
  var decimalBits = new int[4];

  decimalBits[0] = buffer[offset + 0] | (buffer[offset + 1] << 8) | (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24);
  decimalBits[1] = buffer[offset + 4] | (buffer[offset + 5] << 8) | (buffer[offset + 6] << 16) | (buffer[offset + 7] << 24);
  decimalBits[2] = buffer[offset + 8] | (buffer[offset + 9] << 8) | (buffer[offset + 10] << 16) | (buffer[offset + 11] << 24);
  decimalBits[3] = buffer[offset + 12] | (buffer[offset + 13] << 8) | (buffer[offset + 14] << 16) | (buffer[offset + 15] << 24);

  return new Decimal(decimalBits);
}

public byte[] DecimalToBytes(decimal number)
{
  var decimalBuffer = new byte[16];

  var decimalBits = Decimal.GetBits(number);

  var lo = decimalBits.Value[0];
  var mid = decimalBits.Value[1];
  var hi = decimalBits.Value[2];
  var flags = decimalBits.Value[3];

  decimalBuffer[0] = (byte)lo;
  decimalBuffer[1] = (byte)(lo >> 8);
  decimalBuffer[2] = (byte)(lo >> 16);
  decimalBuffer[3] = (byte)(lo >> 24);

  decimalBuffer[4] = (byte)mid;
  decimalBuffer[5] = (byte)(mid >> 8);
  decimalBuffer[6] = (byte)(mid >> 16);
  decimalBuffer[7] = (byte)(mid >> 24);

  decimalBuffer[8] = (byte)hi;
  decimalBuffer[9] = (byte)(hi >> 8);
  decimalBuffer[10] = (byte)(hi >> 16);
  decimalBuffer[11] = (byte)(hi >> 24);

  decimalBuffer[12] = (byte)flags;
  decimalBuffer[13] = (byte)(flags >> 8);
  decimalBuffer[14] = (byte)(flags >> 16);
  decimalBuffer[15] = (byte)(flags >> 24);

  return decimalBuffer;
}

-1

正如其他人所提到的,使用BitConverter类,见下面的示例:

     byte[] bytez = new byte[] { 0x00, 0x00, 0x80, 0x3F };
     float flt = BitConverter.ToSingle(bytez, 0); // 1.0

     bytez = new byte[] { 0x00, 0x00, 0x00, 0x40 };
     flt = BitConverter.ToSingle(bytez, 0); // 2.0

     bytez = new byte[] { 0, 0, 192, 190 };
     flt = BitConverter.ToSingle(bytez, 0); // -0.375

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接