5

Delphiで定数を定義しようとしています:

const
   FNV_offset_basis = 14695981039346656037;

そして、私はエラーを受け取ります:整数定数が大きすぎます

注: 14,695,981,039,346,656,037 10進数は16進数と同じ0x14650FB0739D0383です。

Int64この定数を宣言するにはどうすればよいですか?

私が試した他のいくつかのこと:

const
   FNV_offset_basis: Int64 = 14695981039346656037;
   FNV_offset_basis = Int64(14695981039346656037);
   FNV_offset_basis: Int64 = Int64(14695981039346656037);


var
   offset: LARGE_INTEGER;
begin
   //recalculate constant every function call
   offset.LowPart = $739D0383;
   offset.HighPart = $14650FB0;

修正

私の基本的な仮定は間違っていました。

Windows 7 Calculatorに貼り付け14695981039346656037て、16進数に変換すると、16進数に相当するもの146959810393466560370x14650FB0739D0383次のようになります。

ここに画像の説明を入力してください

それは正しくありません。

したがって、上位ビットが設定されていない16桁の16進値を見たとき、64ビットの符号付き整数に収まると推測しました。

実際には、16進数に相当するもの14695981039346656037は...何か他のものです。ロブ、あなたは正しかった!(おそらく)

4

5 に答える 5

11

問題の16進変換が正しくありません。その数は実際には$cbf29ce484222000であり、符号付き64ビット整数には適合しません。それを表すには、符号なし64ビット整数が必要です。Delphi 5には署名されていないUInt64がないため、運が悪いです。お使いのバージョンのDelphiには、その数値を表すことができる整数データ型はありません。

必要な処理が行われる場合は、ビットパターンを符号付きの値として解釈できます。その場合、負の数になります。

于 2012-04-24T17:36:37.410 に答える
5

その数は、符号付き64ビット整数が保持できる数よりも大きくなります。UInt64代わりに使ってみましたか?

于 2012-04-24T17:30:45.787 に答える
5

64ビット(符号なし)の数値を保持するために必要なのは64ビット変数だけです。私はまだDelphiInt64を使用してそれを達成できますが、秘訣は必要な定数を宣言する方法でした。

const
    FNV_offset_basis: ULARGE_INTEGER = (LowPart: $cbf29ce4; HighPart: $84222000);

(正しい16進値を見つけてくれたDaveとRobに感謝します)

私は厳密に言えば、を使用していませんがInt64、Int64を使用しています:

var
   hash: Int64;
begin
   hash := FNV_offset_basis.QuadPart;

   for i := 1 to Length(s) do
   begin
       hash := hash xor Byte(s[i]);
       hash := UInt64Mul(hash, 1099511628211);       
   end;

   Result := UInt64mod(hash, map.Length);
end;

慎重に作成されたUInt64Xxx数学ルーチンを使用して:

function UInt64mod(const Dividend: Int64; const Divisor: DWORD): DWORD;
var
    d2: LongWord;
    remainder: LongWord;
begin
    //Upper half of dividend cannot be larger than divisior, or else a #de divide error occurs
    //Keep multiplying by two until it's larger.
    //We fixup at the end
    d2 := Divisor;
    while d2 < u.HighPart do
       d2 := d2 * 2;

    asm
        MOV   EDX, ULARGE_INTEGER(Dividend).HighPart;
        MOV   EAX, ULARGE_INTEGER(Dividend).LowPart;
        MOV   ECX, d2;

        //EAX := EDX:EAX / r/m32, EDX=remainder
        DIV   ECX;
        MOV   remainder,EDX
    end;

    //Fixup for using larger divisor
    Result := remainder mod Divisor;
end;

UInt64Mul読者のための演習として実装を残しておきます。

于 2012-04-24T20:23:09.660 に答える
0

Delphi 5でサポートされていないタイプUint64のバリアントを返すWMI呼び出しがありました。Int64が期待した結果に対して十分に公平であると仮定して、1-私は返されたバリアントをタイプキャストして拡張(実型)に格納しました。2 -必要に応じてExtendedからInt64を返す「Trunc」関数を使用しました。

正確にはあなたが望むものではありませんが、リアルタイプを考慮することは誰かがいくつかの「不可能な」Delphi5数学を達成するのを助けるかもしれません。

于 2015-12-01T20:36:01.797 に答える
-1

Windows 7 Calculatorに障害があり、警告なしに最後の桁を削除します。また、QWordが選択されている場合でも、Calculatorは64ビットで実際に計算できないようです。これはWindows7でのみInt64電卓のようであり、十分な桁数を表示できず、単にそれらを完全に間違った値にストリップします。興味深いことに、WindowsXPCalculatorにはこのバグはありません。

また、14695981039346656037の実際の16進値は0xCBF29CE484222325であり、14695981039346656037 =(20921 * 465383 * 1509404459)です。この計算機を使用して計算すると、プログラマーモードでは14695981039346656037(署名なし)ではなく-3750763034362895579(署名済み)になります。科学モードでは正しくなります。

于 2015-04-14T23:18:44.960 に答える