Maison > développement back-end > Golang > Convertir big.Int en int64 et vice versa et complément à deux

Convertir big.Int en int64 et vice versa et complément à deux

王林
Libérer: 2024-02-09 17:51:09
avant
489 Les gens l'ont consulté

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

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.

Contenu de la question

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())
}
Copier après la connexion

Solution

Beaucoup de questions ici :

Le résultat de

value 无法用 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:])
Copier après la connexion

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

en utilisant le complément à deux
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]++
    }
}
Copier après la connexion

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)
}
Copier après la connexion

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!

source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal