9
uses
  SysUtils, Variants;

var
  VariantSingle: Variant;
  VTSingle: TVarType;
  SingleTest: Single;
  VariantDouble: Variant;
  DoubleTest: Double;
  VTDouble: TVarType;

begin
  SingleTest := 1.234;
  VariantSingle := SingleTest;
  VTSingle := VarType(VariantSingle) and varTypeMask;

  DoubleTest := 1.23456;
  VariantDouble := DoubleTest;
  VTDouble := VarType(VariantDouble) and varTypeMask;

  WriteLn(Format('VarType: Single: %d, Double %d', [VTSingle, VTDouble]));
end.

上記のコードは次を出力します。

VarType: シングル: 5、ダブル 5

System.pas から

varSingle   = $0004; { vt_r4           4 }
varDouble   = $0005; { vt_r8           5 }

したがって、VTSingleは 5 ではなく4
になると思い ます。

4

1 に答える 1

7

Delphi ライブラリは、 への呼び出しによって、すべての浮動小数点代入をバリアントに実装することを選択します_VarFromReal。そして、その関数は次のようになります。

procedure _VarFromReal(var V: TVarData; const Value: Real);
begin
  if (V.VType and varDeepData) <> 0 then
    VarClearDeep(V);
  V.VType := varDouble;
  V.VDouble := Value;
end;

これは のタイプを使用することに注意してくださいvarDoubleRealAnd には、 のエイリアスであるへの暗黙的な変換が含まれDoubleます。設計者がなぜその特定のルートを選択したのかはわかりませんが、その選択の結果は、観察される動作です。

varSingle使用できるバリアントを作成する簡単な方法:

VariantSingle := VarAsType(SingleTest, varSingle);

これは に変換SingleTestされますがDouble、再び に戻りSingleます。

その不必要な変換を回避するには、独自のヘルパーを作成します。

function VarFromSingle(const Value: Single): Variant;
begin
  VarClear(Result);
  TVarData(Result).VSingle := Value;
  TVarData(Result).VType := varSingle;
end;

次のように呼び出すことができます:

VariantSingle := VarFromSingle(SingleTest);

この後者のアプローチは、私の意見では正しい解決策です。

于 2013-02-28T10:57:03.413 に答える