如何基于十六进制值创建单个常量,其中十六进制值是无符号整数,单位的原始内存。我想做这样的事情,但它不编译,这将尝试将十六进制值转换为单个,然后存储该转换的结果,而不是存储十六进制值本身:
LARGEST_SINGLE_LESS_THAN_ZERO = Single($80800000);
我收到“无效的Typecast”错误。
例如:
1的单个值在内存中存储为$ 3F800000。我希望能够创建const
,让我使用$ 3F800000而不是1来设置值。
我还尝试了其他变种,例如没有运气:
LARGEST_SINGLE_LESS_THAN_ZERO = PSingle(@$80800000)^;
背景
我有一个方法,当我提供单个值时,我用它来获得下一个最小的单个:
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) = $80000000) or (int32Value = 0) then
begin
// special handling needed for -0 and 0. We need to go to the smallest
// negative number.
int32Value := $80800000;
end
else
begin
if int32Value >= 0 then
Dec(int32Value)
else
Inc(int32Value);
end;
Result := PSingle(@int32Value)^;
end;
这非常有用,因为我们使用的矢量操作只能执行>或者<所以我们用它来做一个> =和一个< =的等价物。我们经常检查0.所以我们需要获取所有数据> = 0我们做这样的事情:
MyVector.ThresholdGT(NextBefore(0));
为其他开发人员提供这些类型操作的常量会更好。尝试使用下面的PSingle格式将无法正常工作,因为该数字不是变量。
答案 0 :(得分:2)
为了使用十六进制值声明单个常量,使其不能被代码更改,可以分两步完成:
const
iLARGEST_SINGLE_LESS_THAN_ZERO : Int32 = $80800000;
var
LARGEST_SINGLE_LESS_THAN_ZERO : Single absolute iLARGEST_SINGLE_LESS_THAN_ZERO;
尝试更改LARGEST_SINGLE_LESS_THAN_ZERO
的值会产生编译错误:Left side cannot be assigned to
。
答案 1 :(得分:1)
由于语言的限制,很难干净地完成这项工作。也许您可以做的最好的事情是创建一个具有重叠的整数和单个字段的变体记录类型。
type
TSingleIntegerVariantRec = record
case Integer of
0: (I: Integer);
1: (S: Single);
end;
一旦有了这种类型,就可以使用整数字段声明类型常量,然后读取单个字段。
const
LARGEST_SINGLE_LESS_THAN_ZERO: TSingleIntegerVariantRec = (I: $80800000);
....
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);
并且仍然没有注意到所有粗糙的实现细节。