在实际开发中,对于超出 int64 或者 uint64 类型的大数进行计算时,如果对精度没有要求,使用 float32 或者float64 就OK,但如果对精度有严格要求的时候,浮点数就不可用了,因为浮点数在内存中只能被近似的表示。
Go语言中 math/big 包实现了大数字的多精度计算,支持 Int(有符号整数)、Rat(有理数)和 Float(浮点数)等数字类型。这些类型可以实现任意位数的数字,只要内存足够大,但缺点是需要更大的内存和处理开销,这使得它们使用起来要比内置的数字类型慢很多。
为实现区块链的搭建,用big.Int进行哈希值的计算再合适不过。
下面是包括big.Int声明,比较大小,移位和与其他类型转换的例子:
package main
import (
"fmt"
"math/big"
)
func main() {
//可以不声明,直接传入NewInt
var v1 int64
var v2 int64
v1 = 10086
v2 = 100086
//创建Int类型,NewInt 只能由 int64 ——> big.Int
a := big.NewInt(v1)
b := big.NewInt(v2)
//比较a和b的大小
//a<b返回-1,a>b返回1,a=b返回0
isValid1 := a.Cmp(b)
//返回bool类型
isValid2 := a.Cmp(b) == 1
isValid3 := a.Cmp(b) == -1
fmt.Println(isValid1)
fmt.Println(isValid2)
fmt.Println(isValid3)
//定义Int
c := big.NewInt(1)
//将a向左移动20位
c.Lsh(c, uint(20))
//10进制
fmt.Printf("将a向左移动20位后为(10进制):%d\n", c)
//16进制
fmt.Printf("将a向左移动20位后为(16进制):%x\n", c)
//将byte数组类型转换为big.Int类型
v3 := []byte{4,5}
hashInt := new(big.Int)
hashInt.SetBytes(v3[:])
fmt.Println(v3)
fmt.Println(hashInt)
//同理:
//string -> big.Int : s.SetString
//big.Int > string : b.String()
//...
}