ホームページ  >  記事  >  バックエンド開発  >  big.Int から int64 への変換、またはその逆、および 2 の補数への変換

big.Int から int64 への変換、またはその逆、および 2 の補数への変換

王林
王林転載
2024-02-09 17:51:09385ブラウズ

将 big.Int 转换为 int64,反之亦然以及二进制补码

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())
}

解決策

ここには多くの問題があります:

valueint64 で表現できないため、value.int64() の結果は未定義です。

下位ビットでは int64 の符号付き結果が考慮されていないため、結果に負の数を加算している可能性があります。 uint64 を使用する必要があります (または、少なくとも big.int に追加する前に変換する必要があります)。

rsh メソッド内で value を変更しているため、値が正しく再作成されたとしても、最終的な比較は失敗します。比較したい場合は、新しい big.int を作成して元の値を保存します。

big.int の生データ表現を正確に 128 ビットにしたい場合は、fillbytes メソッドを使用できます。ビッグエンディアン データを取得して、次のように 2 つの 64 ビット値を構築できます。 リーリー バイト順序が固定されたので、結果に符号ビットを追加します。ただし、

int128

のように機能させるには、2 の補数を使用して記号 を設定する必要があります。 リーリー 新しい

big.int

を作成するには、プロセス全体を逆にします: リーリー 複数のキー値をテストする例:

https://go.dev/play/ p/e1e-5cilflr

出力は符号なしの値として書き込まれるため、maxint128 を超える値で開始できる場合は、符号付きの値がオーバーフローしていないことを確認するチェックも追加する必要があります。

[2]int64

として保存すると、ビットごとの操作に uint64 値が必要であり、int64 値がロールされないようにする必要があるため、さらに混乱します。独自の補完により終了します。この場合、指定された関数に関して [2]int64[2]uint64 を相互に変換する方が簡単です。

以上がbig.Int から int64 への変換、またはその逆、および 2 の補数への変換の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はstackoverflow.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。