phpエディターのYouziが、PHPでbig.Intをint64に変換する方法と、int64をbig.Intに変換する方法を紹介します。コンピューター プログラミングでは、big.Int と int64 は 2 つの異なるデータ型であり、big.Int は大きな整数を処理するために使用され、一方、int64 は 64 ビットの符号付き整数型です。型変換を行うときは、コンピューターで符号付き整数を表現する方法である 2 の補数の概念に注意する必要があります。次に、これら 2 つのタイプ間の変換プロセスについて詳しく説明します。
128ビット整数を表す go big.int を [2]int64 に変換しようとしています。アイデアは、128 ビットの符号付き整数をリトルエンディアンのバイトオーダーにエンコードする Rust の i128::to_le_bytes() と一致できるようにすることです。この例は、Rust の i128::to_le_bytes()
と一致します。 big.int に変換し直そうとすると、同じ値が得られません。最初の右シフトを実行するときに失われたビットはありますか?ありがとう。
package main import ( "encoding/binary" "fmt" "math/big" ) func main() { initial := new(big.Int) initial.SetString("-42", 10) value, _ := new(big.Int).SetString("-42", 10) var result [2]int64 result[0] = value.Int64() result[1] = value.Rsh(value, 64).Int64() leRepresentation := make([]byte, 16) binary.LittleEndian.PutUint64(leRepresentation[:8], uint64(result[0])) binary.LittleEndian.PutUint64(leRepresentation[8:], uint64(result[1])) fmt.Println(leRepresentation) fmt.Println(result) reverse := big.NewInt(result[1]) reverse.Lsh(reverse, 64) reverse.Add(reverse, big.NewInt(result[0])) fmt.Println(reverse.String()) fmt.Println(initial.String() == reverse.String()) }
ここには多くの問題があります:
value
は int64
で表現できないため、value.int64()
の結果は未定義です。
下位ビットでは int64
の符号付き結果が考慮されていないため、結果に負の数を加算している可能性があります。 uint64
を使用する必要があります (または、少なくとも big.int
に追加する前に変換する必要があります)。
rsh
メソッド内で value
を変更しているため、値が正しく再作成されたとしても、最終的な比較は失敗します。比較したい場合は、新しい big.int
を作成して元の値を保存します。
big.int の生データ表現を正確に 128 ビットにしたい場合は、
fillbytes メソッドを使用できます。ビッグエンディアン データを取得して、次のように 2 つの 64 ビット値を構築できます。
リーリー
バイト順序が固定されたので、結果に符号ビットを追加します。ただし、
のように機能させるには、2 の補数を使用して記号 を設定する必要があります。
リーリー
新しい
を作成するには、プロセス全体を逆にします:
リーリー
複数のキー値をテストする例:
出力は符号なしの値として書き込まれるため、maxint128 を超える値で開始できる場合は、符号付きの値がオーバーフローしていないことを確認するチェックも追加する必要があります。
[2]int64 として保存すると、ビットごとの操作に uint64 値が必要であり、int64
値がロールされないようにする必要があるため、さらに混乱します。独自の補完により終了します。この場合、指定された関数に関して [2]int64
と [2]uint64
を相互に変換する方が簡単です。
以上がbig.Int から int64 への変換、またはその逆、および 2 の補数への変換の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。