【问题标题】:Converting float or negative integer to hexadecimal in Borland Delphi在 Borland Delphi 中将浮点数或负整数转换为十六进制
【发布时间】:2010-02-04 15:29:54
【问题描述】:

我编写了一个使用串行连接与某些硬件通信的程序。 它以我的方式发送很多十六进制值(传感器读数),并且每隔一段时间它发送一个负值。 前任。 我收到一个十六进制值:FFFFF5D6 我必须将其转换为:-2602

我遇到的另一个问题是我无法将浮点数转换为十六进制并返回。

有什么简单的方法吗?

【问题讨论】:

  • 您以十六进制显示的数字不是 FLOAT 而是 32 位整数。
  • 没错,我想知道如何转换负整数以及如何转换浮点数

标签: delphi binary hex


【解决方案1】:

您可以使用一个足够大的整数来覆盖所使用的浮点值,然后使用ABSOLUTE 关键字,将十六进制“转换”为浮点数。真正要做的就是将值的内存编码为整数。使用大小完全相同的类型时要非常小心(您可以使用SIZEOF 来查找值的内存大小)。如果您需要一个奇数大小,那么绝对针对一个字节数组并循环并转换为/从每个字节(这将是两个字符的十六进制)。

ABSOLUTE 关键字强制两个变量从同一内存地址开始,从一个写入的任何值都可以立即在另一个中使用。

var
  fDecimal : Double; // size = 8 bytes
  fInteger : Int64 absolute fDecimal;  // size = 8 bytes
begin
  fDecimal := 3.14;
  ShowMessage(format('%x=%f',[fInteger,fDecimal]));
  fInteger := StrToInt64('$1234123412341234');
  ShowMessage(FloatToStr(fDecimal)+'='+Format('%x',[fInteger]));
end;

这是奇数尺寸的花车的例程:

var
  fDecimal : extended;
  fInteger : array[1..10] of byte absolute fDecimal;
  sHex     : string;
  iX       : integer;
begin
  ShowMessage(IntToStr(SizeOf(fDecimal))+':'+IntToStr(SizeOf(fInteger)));
  fDecimal := 3.14;
  sHex := '';
  for iX := 1 to 10 do
    sHex := sHex + IntToHex(fInteger[iX],2);
  ShowMessage(sHex);
  // clear the value
  fDecimal := 0.0;
  // Reload the value
  for iX := 1 to (Length(sHex) DIV 2) do
    fInteger[iX] := StrToInt('$'+Copy(sHex,(Ix*2)-1,2));
  ShowMessage(FloatToStr(fDecimal));
end;

【讨论】:

    【解决方案2】:

    要将十六进制字符串转换为整数,可以使用 StrToInt 函数,也可以检查 TryStrToInt 函数(如果字符串不代表有效数字,则返回 False)。

    uses
    SysUtils;
    
    var
    ivalue : integer;
    begin
    ivalue:=StrToInt('$FFFFF5D6'); // Hexadecimal values start with a '$' in Delphi
    
    ..
    end;
    

    对于浮点数的十六进制表示,您可以查看这些文章。

    【讨论】:

    • 感谢这对十六进制到十进制有效,但反过来也可以吗?
    • 要将整数转换为十六进制字符串,请调用IntToHex
    【解决方案3】:

    我从未见过以十六进制表示的浮点数,因此您必须弄清楚设备为此使用的确切格式。对于负数情况,您需要使用 HexToInt 将其转换为整数,然后确定该整数是否大于表示硬件整数数据类型的 MaxInt 的任何阈值。如果它大于那个,它是一个负数,这意味着你需要,IIRC,获取数字的 1s 补码并将其转换为负数。

    【讨论】:

    • 很好,除了 Delphi 没有 HexToInt()。不过,您可以改用 StrToInt('$' + YourHexString) 。根据我的经验,+1 表示没有以十六进制表示的浮点数。
    • 如果您从未见过以十六进制表示的浮点数,请查看 C99 标准,例如 redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gcc/…
    • 您是说您知道问题中的设备使用的是 C99 标准?
    • 啊,原来我已经将 StrToInt64 包装在一个名为 HexToInt 的函数中。这段代码是五年前写的。
    【解决方案4】:

    如果要分开指数和有效数字,可以使用变体记录:

      TExtRec = packed record
        case Boolean of
          false:
            (AValue: Extended);
          true:
            (ASignificand: uint64; ASignExp: uint16;)
      end;
    

    我认为这有助于理解浮点数的结构。

    示例用法:

    var
      r: TExtRec;
    begin
      r.AValue := 123.567;
      ShowMessage(IntToHex(r.ASignExp) + IntToHex(r.ASignificand));
    end;
    

    输出:

     4005F7224DD2F1A9FBE7
    

    You can calculate it back:

    v = (-1)s * 2(e-16383) * (i.f)
    

    • e = $4005 = 16389
    • i.f = $F7224DD2F1A9FBE7
    • i.f = 1.930734374999999999954029827886614611998084001243114471435546875
    • v=123.566999999999999997057908984743335167877376079559326171875

    为了转换i.f,我使用了binary converter

    【讨论】:

      猜你喜欢
      • 2014-03-01
      • 2016-06-02
      • 2010-12-08
      • 1970-01-01
      • 1970-01-01
      • 2012-08-04
      • 2019-04-30
      • 2016-06-01
      相关资源
      最近更新 更多