[英]Convert negative digit in byte slice to int
我需要幫助
Debezium( https://debezium.io/ )將base64字符串中的十進制數字轉換為整數,並以json中的參數作為精度。
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
但是在Golang中,類似的例子有些麻煩
包主
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-返回9777216
因為當我在“ math / big / Int”中使用SetBytes時,它總是將數字設置為正數
// 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
}
Java的BigInteger
構造方法期望數字以2的補碼二進制表示形式,而Go的big.Int.SetBytes()
期望無符號整數值(按大端字節順序):
SetBytes將buf解釋為大端無符號整數的字節,將z設置為該值,然后返回z。
我們可以使用Int.SetBytes()
進行操作,但是如果數字為負數,我們必須將其轉換為2的補碼表示的二進制數據的數字。 我們可以判斷它的第一位是否為1(這是第一個字節的最高位)是否為負。
這種轉換很簡單:如果輸入使用n
個字節表示,則使用n+1
個字節構造一個數字,其中第一個為1
,其余為0
(使用n
個字節加1的最大可表示數字)。 從該數字減去( Int.Sub()
)的輸入將得出2的補數形式的數字的絕對值,因此我們只需要在此數字上Int.Neg()
一個負號: Int.Neg()
。
可以通過將結果( Int.Div()
)除以10
的數字來應用scale
。 我們可以通過將零scale
附加到1
來構造這樣的數字。
這是一個完成所有這些操作的decode()
函數。 它並未針對性能進行優化,但可以完成以下工作:
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
}
測試示例:
n, err := decode("lTBA", 4)
fmt.Println(n, err)
輸出(在Go Playground上嘗試):
-700 <nil>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.