Maison > Article > développement back-end > Convertir big.Int en int64 et vice versa et complément à deux
l'éditeur php Yuzi vous présentera comment convertir big.Int en int64 en PHP, et comment convertir int64 en big.Int. En programmation informatique, big.Int et int64 sont deux types de données différents. big.Int est utilisé pour gérer de grands entiers, tandis que int64 est un type entier signé de 64 bits. Lors de la conversion de type, nous devons prêter attention au concept de complément à deux, qui est une manière de représenter des entiers signés dans les ordinateurs. Nous détaillerons ensuite le processus de conversion entre ces deux types.
J'essaie de convertir go big.int représentant un entier de 128 bits en [2]int64. L'idée est de pouvoir faire correspondre i128::to_le_bytes() de rust, qui code les entiers signés de 128 bits dans l'ordre des octets petit-boutien. Cet exemple correspond à celui de Rust i128::to_le_bytes()
. Chaque fois que j'essaie de le reconvertir en big.int, je n'obtiens pas la même valeur. Des bits sont-ils perdus lors du décalage initial vers la droite ? Merci.
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()) }
Beaucoup de questions ici :
Le résultat devalue
无法用 int64
表示,因此 value.int64()
est indéfini.
Vos bits inférieurs ne sont pas pris en compte int64
的签名结果,因此您可能会在结果中添加负数。您需要使用 uint64
(或者至少在将其添加到 big.int
avant de les convertir).
Vous rsh
方法中改变 value
,因此即使正确重新创建了该值,最后的比较也会失败。如果要比较的话,新建一个 big.int
stockez la valeur d'origine.
Si tu veux big.int
的原始数据表示形式恰好为 128 位,您可以使用 fillbytes
méthode. Nous pouvons prendre des données big-endian et construire 2 valeurs 64 bits comme ceci :
b := make([]byte, 16) value.fillbytes(b) var result [2]uint64 result[0] = binary.bigendian.uint64(b[:8]) result[1] = binary.bigendian.uint64(b[8:])
Maintenant que l'ordre des octets est corrigé, ajoutez le bit de signe au résultat. Cependant, pour que cela fonctionne comme int128
, nous devons définir le symbole
const sign = uint64(1 << 63) if value.sign() < 0 { // convert the unsigned value to two's compliment result[0] = ^result[0] result[1] = ^result[1] result[1]++ // check for carry if result[1] == 0 { result[0]++ } }
Pour créer un nouveau big.int
, inversez tout le processus :
neg := uint128[0]&sign != 0 if neg { // reverse the two's compliment if uint128[1] == 0 { uint128[0]-- } uint128[1]-- uint128[0] = ^uint128[0] uint128[1] = ^uint128[1] } b := make([]byte, 16) binary.BigEndian.PutUint64(b[:8], uint128[0]) binary.BigEndian.PutUint64(b[8:], uint128[1]) result := new(big.Int).SetBytes(b) if neg { result.Neg(result) }
Exemple de test de plusieurs valeurs clés : https://go.dev/play/ p/e1e-5cilflr
Étant donné que la sortie est écrite sous forme de valeur non signée, si vous pouvez commencer avec une valeur > maxint128, vous devez également ajouter une vérification pour vous assurer que les valeurs signées ne sont pas dépassées. Il est plus facile de les convertir les uns vers les autres en les stockant sous [2]int64
会更加混乱,因为我们需要 uint64 值进行按位运算,并且我们需要确保 int64
值不会通过它们自己的补码进行滚动。在这种情况下,围绕给定函数将 [2]int64
与 [2]uint64
.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!