Converter dígito negativo em fatia byte para int

frankegoesdown:

eu preciso de ajuda

Debezium ( https://debezium.io/ ) dígitos convertido decimais como um número inteiro string de base64 com precisão como parâmetro no JSON em java que decodificados como neste exemplo

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Base64;

public class HelloWorld{

     public static void main(String []args){
        String encoded = "lTBA";
        int scale = 4;
        final BigDecimal decoded = new BigDecimal(new BigInteger(Base64.getDecoder().decode(encoded)), scale);
        System.out.println(decoded);        
     }
}

"lTBA" = -700

mas em golang Eu tenho alguns problemas no exemplo semelhante

pacote principal

import (
    "encoding/base64"
    "fmt"
    "math/big"
)

func main() {
    data, _ := base64.StdEncoding.DecodeString("lTBA")

    bigInt := new(big.Int).SetBytes(data).String()
    fmt.Println(bigInt)
}

https://play.golang.org/p/3Xdq9x6B9V- Ele retorna9777216

Porque quando eu uso setBytes em "math / grande / Int"-lo conjunto de dígitos como positivo sempre

// SetBytes interprets buf as the bytes of a big-endian unsigned
// integer, sets z to that value, and returns z.
func (z *Int) SetBytes(buf []byte) *Int {
    z.abs = z.abs.setBytes(buf)
    z.neg = false
    return z
}
icza:

Construtor de do Java BigIntegerespera que o número em complemento de 2 representação binária, enquanto o Go big.Int.SetBytes()espera um valor inteiro sem sinal (em ordem de bytes big-endian):

SetBytes interpreta buf como os bytes de um grande endian inteiro sem sinal , conjuntos de z para que o valor, e retorna z.

O que podemos fazer é continuar usando Int.SetBytes(), mas se o número for negativo, temos que transformá-lo para o número dos dados binários representados em complemento de 2. Nós podemos dizer se é negativo se seu primeiro bit é 1 (que é o mais alto bit do primeiro byte).

Esta transformação é simples: se a entrada é representado usando nbytes, construir um número utilizando n+1bytes, onde o primeiro é 1, o resto é 0(o número máximo representável utilizando nbytes mais 1). Subtraindo ( Int.Sub()) a entrada deste número vai dar-lhe o valor absoluto do número em complemento de 2, por isso só temos de aplicar um sinal negativo sobre este número: Int.Neg().

A escala pode ser aplicada através da divisão ( Int.Div()) o resultado por ser um número 10scale. Podemos construir tais número um anexando scalezeros para um 1.

Aqui está uma decode()função que faz tudo isso. Não é otimizado para desempenho, mas ele faz o trabalho:

func decode(in string, scale int) (out *big.Int, err error) {
    data, err := base64.StdEncoding.DecodeString(in)
    if err != nil {
        return
    }

    out = new(big.Int).SetBytes(data)

    // Check if negative:
    if len(data) > 0 && data[0]&0x80 != 0 {
        // It's negative.
        // Convert 2's complement negative to abs big-endian:
        data2 := make([]byte, len(data)+1)
        data2[0] = 1
        temp := new(big.Int).SetBytes(data2)
        out.Sub(temp, out)

        // Apply negative sign:
        out.Neg(out)
    }

    // Apply scale:
    if scale > 0 {
        temp, _ := new(big.Int).SetString("1"+strings.Repeat("0", scale), 10)
        out.Div(out, temp)
    }

    return
}

Exemplo testando-a:

n, err := decode("lTBA", 4)
fmt.Println(n, err)

Saída (experimentá-lo na Go Playground ):

-700 <nil>

Acho que você gosta

Origin http://43.154.161.224:23101/article/api/json?id=234211&siteId=1
Recomendado
Clasificación