Delphi: 从二进制表示定义 const double
Delphi: define const double from binary representation
背景
我想创建一个单元测试来测试 Delphi 的一些 rtl 方面,为了做到这一点,我想使用非常具体的 IEEE 浮点值,我想直接从它们的二进制表示中创建这些值.
到目前为止,我已经想出了这个例程,而且它确实起到了作用。
function TestIEEEDouble.BuildDoubleFromRawInt64(const aBinData:UInt64):double;
begin
CheckEquals(sizeof(aBinData),sizeof(Result),'sizeof(aBinData),Sizeof(Result)'); // ensures we dont mess up with wrong types
Move(aBinData,Result,sizeof(Result));
end;
使用如下(bindata可能还是错的,但问题不是这个):
procedure TestIEEEDouble.Setup;
begin
inherited;
FSmallestPositiveDouble:=BuildDoubleFromRawInt64([=12=]00000000000001);
FSmallestNegativeDouble:=BuildDoubleFromRawInt64(00000000000001);
FLargestPositiveDouble :=BuildDoubleFromRawInt64(FEFFFFFFFFFFFFF);
FLargestNegativeDouble :=BuildDoubleFromRawInt64(FEFFFFFFFFFFFFF);
end;
问题
是否有允许直接从二进制(十六进制)表示形式创建 const double
的语法,如下所示:
const
cSmallestPositiveDouble:double=double([=13=]00000000000001);
结果显然不应该是 1.0
(使用这种语法)而是(接近)4.94065645841247e-324
这可以直接通过工会完成:
type // In a union all variables share the same address
TAll= packed record
case Integer of
1:( d: Double );
2:( i: Int64 );
3:( f: TFileTime );
end;
const // Define the constant just like you would define an array
ALL: TAll= ( i: 43 );
其余的很明显:要么您现在访问 ALL.d
以查看 43
作为 Int64
如何被解释为 Double
。或者反过来做。同样,您甚至可以通过访问 ALL.f
.
检查 TFileTime
解释的外观
在处理或检查二进制文件时,请记住字节顺序也很重要 (LE versus BE) - 特别是从不同的存储类型(FS 与 RAM)读取时。
用我自己的初始解决方案来回答,语法比我喜欢的要广泛一些,但这似乎可以使用变体记录和隐式类型转换来解决问题。
不错的feature/side效果是可以在inspector/watchwindow.
中快速看到二进制表示和双精度表示
type
RDoubleHelperRec=record
class operator Implicit(aRec:RDoubleHelperRec):double;
case Bin:boolean of
True:
(BinData:UINT64);
False:
(DoubleData:double);
end;
...
class operator RDoubleHelperRec.Implicit(aRec: RDoubleHelperRec): double;
begin
Result:=aRec.DoubleData;
end;
然后在使用的时候声明为const:
procedure TestIEEEDouble.TestCompareValueBoundary;
const
cSmallestPositiveDouble:RDoubleHelperRec=(BinData:[=11=]00000000000001);
begin
CheckEquals(0,CompareValue(FSmallestPositiveDouble,cSmallestPositiveDouble),'CompareValue(FSmallestPositiveDouble,cSmallestPositiveDouble)');
end;
背景
我想创建一个单元测试来测试 Delphi 的一些 rtl 方面,为了做到这一点,我想使用非常具体的 IEEE 浮点值,我想直接从它们的二进制表示中创建这些值.
到目前为止,我已经想出了这个例程,而且它确实起到了作用。
function TestIEEEDouble.BuildDoubleFromRawInt64(const aBinData:UInt64):double;
begin
CheckEquals(sizeof(aBinData),sizeof(Result),'sizeof(aBinData),Sizeof(Result)'); // ensures we dont mess up with wrong types
Move(aBinData,Result,sizeof(Result));
end;
使用如下(bindata可能还是错的,但问题不是这个):
procedure TestIEEEDouble.Setup;
begin
inherited;
FSmallestPositiveDouble:=BuildDoubleFromRawInt64([=12=]00000000000001);
FSmallestNegativeDouble:=BuildDoubleFromRawInt64(00000000000001);
FLargestPositiveDouble :=BuildDoubleFromRawInt64(FEFFFFFFFFFFFFF);
FLargestNegativeDouble :=BuildDoubleFromRawInt64(FEFFFFFFFFFFFFF);
end;
问题
是否有允许直接从二进制(十六进制)表示形式创建 const double
的语法,如下所示:
const
cSmallestPositiveDouble:double=double([=13=]00000000000001);
结果显然不应该是 1.0
(使用这种语法)而是(接近)4.94065645841247e-324
这可以直接通过工会完成:
type // In a union all variables share the same address
TAll= packed record
case Integer of
1:( d: Double );
2:( i: Int64 );
3:( f: TFileTime );
end;
const // Define the constant just like you would define an array
ALL: TAll= ( i: 43 );
其余的很明显:要么您现在访问 ALL.d
以查看 43
作为 Int64
如何被解释为 Double
。或者反过来做。同样,您甚至可以通过访问 ALL.f
.
TFileTime
解释的外观
在处理或检查二进制文件时,请记住字节顺序也很重要 (LE versus BE) - 特别是从不同的存储类型(FS 与 RAM)读取时。
用我自己的初始解决方案来回答,语法比我喜欢的要广泛一些,但这似乎可以使用变体记录和隐式类型转换来解决问题。
不错的feature/side效果是可以在inspector/watchwindow.
中快速看到二进制表示和双精度表示type
RDoubleHelperRec=record
class operator Implicit(aRec:RDoubleHelperRec):double;
case Bin:boolean of
True:
(BinData:UINT64);
False:
(DoubleData:double);
end;
...
class operator RDoubleHelperRec.Implicit(aRec: RDoubleHelperRec): double;
begin
Result:=aRec.DoubleData;
end;
然后在使用的时候声明为const:
procedure TestIEEEDouble.TestCompareValueBoundary;
const
cSmallestPositiveDouble:RDoubleHelperRec=(BinData:[=11=]00000000000001);
begin
CheckEquals(0,CompareValue(FSmallestPositiveDouble,cSmallestPositiveDouble),'CompareValue(FSmallestPositiveDouble,cSmallestPositiveDouble)');
end;