go-biggergoland大数库1.引入如下git

  在go语言中我们知道整形只有byte、int32以及int64等而浮点数只有float32和float64基本数据类型。有时候根据需求需要使用大数操作,go中的big包中带了NewInt以及NewFloat,但是提供的api较少,可供初始化的只能使用基本数据类型。不能使用字符串进行初始化。于是本人参考java的大数类进行开发go-bigger并且提供丰富的API调用。github:

github:github.com/SineyCoder/…

内置BigInteger结构体和BigDecimal结构体,包括简单的加减乘除取模等操作。对于高精度的浮点类型BigDecimal目前正在开发阶段,后续会陆续上线。 

下面简单介绍用法:

1. 引入如下github模块

go get github.com/sineycoder/go-bigger
复制代码

2. BigInteger

初始化BigInteger

a:=bigger.NewBigIntegerString("112233")
//或者
a:=bigger.NewBigIntegerLong(112233)

2.1 BigInteger的Add:

func main() {
	a := bigger.ValueOf(6782613786431)
	b := bigger.ValueOf(-678261378231)
	res := a.Add(b)
	fmt.Println(res.String())
}
复制代码

结果: 6104352408200

2.2 BigInteger的Subtract:

func main() {
	a := bigger.ValueOf(6782613786431)
	b := bigger.ValueOf(-678261378231)
	res := a.Subtract(b)
	fmt.Println(res.String())
}
复制代码

结果: 7460875164662

2.3 BigInteger的Divide:

func main() {
	a := bigger.ValueOf(6782613786431)
	b := bigger.ValueOf(-678261378231)
	res := a.Divide(b)
	fmt.Println(res.String())
}
复制代码

结果: -10

2.4 BigInteger的Multiply:

func main() {
	a := bigger.ValueOf(6782613786431)
	b := bigger.ValueOf(-678261378231)
	res := a.Multiply(b)
	fmt.Println(res.String())
}
复制代码

结果: -4600384974793271546583561

3. BigDecimal

BigDecimal初始化:目前仅支持字符串的初始化,可以满足大部分需求!

a:=bigger.NewBigDecimalString("112233.112")

3.1 BigDecimal的Add:

func BenchmarkBiggerFloatAdd(bb *testing.B) {
	a := bigger.NewBigDecimalString("534151451245")
	b := bigger.NewBigDecimalString("18979412")
	a.Add(b)
}
复制代码

3.2 BigDecimal的Substract:

func BenchmarkBiggerFloatSubtract(bb *testing.B) {
	a := bigger.NewBigDecimalString("534151451245")
	b := bigger.NewBigDecimalString("18979412")
	a.Subtract(b)
}
复制代码

3.3 BigDecimal的Multiply:

func BenchmarkBiggerFloatMultiply(bb *testing.B) {
	a := bigger.NewBigDecimalString("534151451245")
	b := bigger.NewBigDecimalString("18979412")
	a.Multiply(b)
}
复制代码

3.4 BigDecimal的Divide:

func BenchmarkBiggerFloatDivide(bb *testing.B) {
	a := bigger.NewBigDecimalString("1")
	b := bigger.NewBigDecimalString("3")
	a.Divide(b, 5, bigger.ROUND_HALF_UP)
}
复制代码

4. 与go内置函数性能对比

4.1 测试代码:


// testing Integer, bigger.bigInteger vs bigInt
func BenchmarkBiggerIntegerAdd(bb *testing.B) {
	a := bigger.BigIntegerValueOf(types.Long(534151451245))
	b := bigger.BigIntegerValueOf(types.Long(18979412))
	a.Add(b)
}
func BenchmarkBigintIntegerAdd(bb *testing.B) {
	a := big.NewInt(534151451245)
	b := big.NewInt(18979412)
	a.Add(a, b)
}

func BenchmarkBiggerIntegerSubtract(bb *testing.B) {
	a := bigger.BigIntegerValueOf(types.Long(534151451245))
	b := bigger.BigIntegerValueOf(types.Long(18979412))
	a.Subtract(b)
}
func BenchmarkBigintIntegerSubtract(bb *testing.B) {
	a := big.NewInt(534151451245)
	b := big.NewInt(18979412)
	a.Sub(a, b)
}

func BenchmarkBiggerIntegerMultiply(bb *testing.B) {
	a := bigger.BigIntegerValueOf(types.Long(534151451245))
	b := bigger.BigIntegerValueOf(types.Long(18979412))
	a.Multiply(b)
}
func BenchmarkBigintIntegerMultiply(bb *testing.B) {
	a := big.NewInt(534151451245)
	b := big.NewInt(18979412)
	a.Mul(a, b)
}

func BenchmarkBiggerIntegerDivide(bb *testing.B) {
	a := bigger.BigIntegerValueOf(types.Long(534151451245))
	b := bigger.BigIntegerValueOf(types.Long(18979412))
	a.Divide(b)
}
func BenchmarkBigintIntegerDivide(bb *testing.B) {
	a := big.NewInt(534151451245)
	b := big.NewInt(18979412)
	a.Div(a, b)
}



// testing Float, bigger.bigDecimal vs bigFloat
func BenchmarkBiggerFloatAdd(bb *testing.B) {
	a := bigger.NewBigDecimalString("534151451245")
	b := bigger.NewBigDecimalString("18979412")
	a.Add(b)
}
func BenchmarkBigintFloatAdd(bb *testing.B) {
	a := big.NewFloat(534151451245)
	b := big.NewFloat(18979412)
	a.Add(a, b)
}

func BenchmarkBiggerFloatSubtract(bb *testing.B) {
	a := bigger.NewBigDecimalString("534151451245")
	b := bigger.NewBigDecimalString("18979412")
	a.Subtract(b)
}
func BenchmarkBigintFloatSubtract(bb *testing.B) {
	a := big.NewFloat(534151451245)
	b := big.NewFloat(18979412)
	a.Sub(a, b)
}

func BenchmarkBiggerFloatMultiply(bb *testing.B) {
	a := bigger.NewBigDecimalString("534151451245")
	b := bigger.NewBigDecimalString("18979412")
	a.Multiply(b)
}
func BenchmarkBigintFloatMultiply(bb *testing.B) {
	a := big.NewFloat(534151451245)
	b := big.NewFloat(18979412)
	a.Mul(a, b)
}

func BenchmarkBiggerFloatDivide(bb *testing.B) {
	a := bigger.NewBigDecimalString("1")
	b := bigger.NewBigDecimalString("3")
	a.Divide(b, 5, bigger.ROUND_HALF_UP)
}
func BenchmarkBigintFloatDivide(bb *testing.B) {
	a := big.NewFloat(0.5)
	b := big.NewFloat(0.4)
	a.Quo(a, b)
}
复制代码

4.2 结果输出:

BenchmarkBiggerIntegerAdd
BenchmarkBiggerIntegerAdd-12             1000000000             0.0000024 ns/op
BenchmarkBigintIntegerAdd
BenchmarkBigintIntegerAdd-12             1000000000             0.0000017 ns/op
BenchmarkBiggerIntegerSubtract
BenchmarkBiggerIntegerSubtract-12        1000000000             0.0000023 ns/op
BenchmarkBigintIntegerSubtract
BenchmarkBigintIntegerSubtract-12        1000000000             0.0000015 ns/op
BenchmarkBiggerIntegerMultiply
BenchmarkBiggerIntegerMultiply-12        1000000000             0.0000032 ns/op
BenchmarkBigintIntegerMultiply
BenchmarkBigintIntegerMultiply-12        1000000000             0.0000022 ns/op
BenchmarkBiggerIntegerDivide
BenchmarkBiggerIntegerDivide-12          1000000000             0.0000025 ns/op
BenchmarkBigintIntegerDivide
BenchmarkBigintIntegerDivide-12          1000000000             0.0000015 ns/op
BenchmarkBiggerFloatAdd
BenchmarkBiggerFloatAdd-12               1000000000             0.0000022 ns/op
BenchmarkBigintFloatAdd
BenchmarkBigintFloatAdd-12               1000000000             0.0000023 ns/op
BenchmarkBiggerFloatSubtract
BenchmarkBiggerFloatSubtract-12          1000000000             0.0000024 ns/op
BenchmarkBigintFloatSubtract
BenchmarkBigintFloatSubtract-12          1000000000             0.0000028 ns/op
BenchmarkBiggerFloatMultiply
BenchmarkBiggerFloatMultiply-12          1000000000             0.0000027 ns/op
BenchmarkBigintFloatMultiply
BenchmarkBigintFloatMultiply-12          1000000000             0.0000028 ns/op
BenchmarkBiggerFloatDivide
BenchmarkBiggerFloatDivide-12            1000000000             0.0000026 ns/op
BenchmarkBigintFloatDivide
BenchmarkBigintFloatDivide-12            1000000000             0.0000025 ns/op
PASS

 4.3 结论:

以下使用benchmark测试其性能,观察发现,BigInteger中,math/big的性能会更加优一点,但是相差无几,在1.5倍差距左右。在浮点数计算中,性能完全一致,有时更优。

5.go中NewFloat精度问题

在go中math下的big包中,NewFloat实际上存在精度问题,如下代码:

得出的结果为0.8999999999999999。这明显是浮点数计算导致的问题。我设计的bigger包中不存在此类问题。

func main() {
	a := big.NewFloat(0.2)
	b := big.NewFloat(0.7)
	res := a.Add(a, b)
	fmt.Println(res) //0.8999999999999999
}
复制代码

如下代码,为bigger包中bigDecimal所得出的结果:

func main() {
	a := bigger.NewBigDecimalString("0.2")
	b := bigger.NewBigDecimalString("0.7")
	res := a.Add(b)
	res = res.SetScale(12, bigger.ROUND_HALF_UP)
	fmt.Println(res.String()) // 0.900000000000
}
复制代码