使用 Delphi 中的十六进制内存值的常量单

Constant single using the hex memory value in Delphi

如何根据十六进制值创建单个常量,其中该十六进制值是一个无符号整数和单个的原始内存。我想做这样的事情,但它不编译,这将尝试将十六进制值转换为单个值,然后存储该转换的结果而不是存储十六进制值本身:

LARGEST_SINGLE_LESS_THAN_ZERO = Single(800000);

我收到 "Invalid Typecast" 错误。

例如:

1 的单个值在内存中存储为 $3F800000。我希望能够创建一个 const,让我使用 $3F800000 而不是 1 来设置值。

我也试过其他变体,比如这个,但运气不好:

LARGEST_SINGLE_LESS_THAN_ZERO = PSingle(@800000)^;

背景

我有一个方法,当提供单个值时,我可以使用该方法获取下一个最小的单个值:

type
  PInt32 = ^Int32;

function NextBefore(const aValue: Single): Single;
var
  int32Value: Int32;
begin
  // this function ignores special values nan/inf
  int32Value := PInt32(@aValue)^;
  if (UInt32(int32Value) = 000000) or (int32Value = 0) then
  begin
    // special handling needed for -0 and 0. We need to go to the smallest
    // negative number.
    int32Value := 800000;
  end
  else
  begin
    if int32Value >= 0 then
      Dec(int32Value)
    else
      Inc(int32Value);
  end;
  Result := PSingle(@int32Value)^;
end;

这非常有用,因为我们使用只能执行 > 或 < 的矢量运算,所以我们用它来执行等同于 >= 和 <= 的操作。我们经常检查 0。所以在我们需要获取所有数据 >= 0 的地方,我们做这样的事情:

MyVector.ThresholdGT(NextBefore(0));

最好为其他开发人员提供这些类型操作的常量。尝试使用下面的 PSingle 格式将不起作用,因为数字不是变量。

由于语言的限制,很难干净地做到这一点。也许您能做的最好的事情就是制作一个同时具有整数和单个字段重叠的变体记录类型。

type
  TSingleIntegerVariantRec = record
    case Integer of
      0: (I: Integer);
      1: (S: Single);
  end;

一旦你有了可用的类型,你就可以使用整数字段声明类型化常量,然后读取单个字段。

const
  LARGEST_SINGLE_LESS_THAN_ZERO: TSingleIntegerVariantRec = (I: 800000);
.... 
MyVector.ThresholdGT(LARGEST_SINGLE_LESS_THAN_ZERO.S);

如果您想添加额外的细微差别,您可以对 Single 实施隐式转换运算符,这样您就可以省略 .S。如果您使该运算符内联,那么我怀疑发出的代码会非常有效。

这可以满足您的要求,但我不会说它非常优雅。我们是我,我会将使用下一个值的代码移动到库函数中,以便您可以传递 0 并使库的使用者免受这些实现细节的影响。

换句话说,您将添加一个 ThresholdGTequal 方法,该方法是这样实现的:

procedure TMyVector.ThresholdGTequal(const Value: Single);
begin
  ThresholdGT(NextBefore(Value));
end;

那么这段代码的消费者只需写:

MyVector.ThresholdGTequal(0);

并且对所有复杂的实施细节都视而不见。

为了以不能被代码更改的方式声明一个具有十六进制值的常量,可以分两步完成:

const 
  iLARGEST_SINGLE_LESS_THAN_ZERO : Int32 = 800000; 
var 
  LARGEST_SINGLE_LESS_THAN_ZERO : Single absolute iLARGEST_SINGLE_LESS_THAN_ZERO;

尝试更改 LARGEST_SINGLE_LESS_THAN_ZERO 的值将给出编译器错误:Left side cannot be assigned to.