big.Int

big.Int是Go超大整型数据的结构。它可以进行超大收据的运算和比较等操作。

初始化

通过整型字面量或int64创建

big.NewInt函数可以基于一个int64整型数据或整型字面量创建一个big.Int实例:

package main

import "math/big"

func main() {
	var (
		num int = 6
	)
	number1 := big.NewInt(int64(num))
	
	number2 := big.NewInt(6)
}

通过字符串创建

big.Int实例的SetString方法可以通过字符串来创建一个big.Int实例。该方法返回两个数据,一个big.Int实例,和一个bool值用来表示成功还是失败。

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number, ok := new(big.Int).SetString("123000001230011", 10)
	if !ok {
		fmt.Println("create big.Int failed")
		return
	}
	fmt.Println(number)
	// 123000001230011
}

SetString允许指定数字的进制。创建的结果仍然是十进制的大整型数据:

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number, ok := new(big.Int).SetString("110000011010101010101", 2)
	if !ok {
		fmt.Println("create big.Int failed")
		return
	}
	fmt.Println(number)
	// 1586517
}

运算

使用Add方法进行加法运算。需要注意的是Add方法返回一个big.Int实例,但通过地址不难看出,返回的实例与第一个加数相同。

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number1 := big.NewInt(123)
	number2 := big.NewInt(456)
	result := number1.Add(number1, number2)
	fmt.Println(result, number1, number2)
	// 579 579 456
	println(result, number1, number2)
	// 0x140000b0000 0x140000b0000 0x140000b0020
}

Sub方法进行减法运算,并与加法参数和返回值相似:

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number1 := big.NewInt(123)
	number2 := big.NewInt(456)
	result := number1.Sub(number1, number2)
	fmt.Println(result, number1, number2)
	// -333 -333 456
	println(result, number1, number2)
	// 0x14000132000 0x14000132000 0x14000132020
}

Mul用于乘法运算:

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number1 := big.NewInt(123)
	number2 := big.NewInt(456)
	result := number1.Mul(number1, number2)
	fmt.Println(result, number1, number2)
	// 56088 56088 456
	println(result, number1, number2)
	// 0x14000132000 0x14000132000 0x14000132020
}

Quo用于除法运算:

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number1 := big.NewInt(400)
	number2 := big.NewInt(100)
	result := number1.Quo(number1, number2)
	fmt.Println(result, number1, number2)
	// 4 4 100
	println(result, number1, number2)
	// 0x14000132000 0x14000132000 0x14000132020
}

如果除数为0,那么panic: division by zero被抛出:

package main

import (
	"fmt"
	"math/big"
)

func main() {
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println(err)
			// division by zero
		}
	}()
	
	number1 := big.NewInt(7)
	number2 := big.NewInt(0)
	result := number1.Quo(number1, number2)
	fmt.Println(result, number1, number2)
	println(result, number1, number2)
}

求余

Rem用于求余运算:

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number1 := big.NewInt(7)
	number2 := big.NewInt(3)
	result := number1.Rem(number1, number2)
	fmt.Println(result, number1, number2)
	// 1 1 3
	println(result, number1, number2)
	// 0x14000132000 0x14000132000 0x14000132020
}

如果除数为0,那么panic: division by zero被抛出:

package main

import (
	"fmt"
	"math/big"
)

func main() {
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println(err)
			// division by zero
		}
	}()

	number1 := big.NewInt(7)
	number2 := big.NewInt(0)
	result := number1.Rem(number1, number2)
	fmt.Println(result, number1, number2)
	// 1 1 3
	println(result, number1, number2)
	// 0x14000132000 0x14000132000 0x14000132020
}

绝对值

Abs方法获取big.Int实例的绝对值,返回的值仍然是一个big.Int实例:

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number := big.NewInt(-7)
	result := number.Abs(number)
	fmt.Println(result, number)
	// 7 7
	println(result, number)
	// 0x14000132000 0x14000132000
}

比较

Cmp方法用于比较两个big.Int实例的数值大小,CmpAbs方法用于比较两个big.Int实例数值绝对值大小。

  • 若number1 > number2,Cmp/CmpAbs方法返回1
  • 若number1 = number2,Cmp/CmpAbs方法返回0
  • 若number1 < number2,Cmp/CmpAbs方法返回-1
package main

import (
	"fmt"
	"math/big"
)

func main() {
	number1 := big.NewInt(200)
	number2 := big.NewInt(500)
	number3 := big.NewInt(200)

	result := number1.Cmp(number2)
	fmt.Println(result)
	// -1

	result = number2.Cmp(number3)
	fmt.Println(result)
	// 1

	result = number1.Cmp(number3)
	fmt.Println(result)
	// 0

	number4 := big.NewInt(-200)
	result = number4.CmpAbs(number1)
	fmt.Println(result)
	// 0
}

移位

Lsh方法进行位左移运算,Rsh方法进行位右移运算。

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number1 := big.NewInt(4)
	// same as 4 << 1
	result := number1.Lsh(number1, 1)
	fmt.Println(result, number1) // 8 8
	println(result, number1)     // 0x14000132000 0x14000132000

	number2 := big.NewInt(-4)
	// same as -4 >> 1
	result = number2.Rsh(number2, 1)
	fmt.Println(result, number2) // -2 -2
	println(result, number2)     // 0x14000128020 0x14000128020
}

And方法进行与运算:

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number1 := big.NewInt(9)
	number2 := big.NewInt(3)

	// Same as 9 & 3
	result := number1.And(number1, number2)
	fmt.Println(result, number1, number2) // 1 1 3
	println(result, number1, number2)     // 0x14000132000 0x14000132000 0x14000132020
}

Or方法进行或运算:

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number1 := big.NewInt(5)
	number2 := big.NewInt(3)

	// Same as 5 | 3
	result := number1.Or(number1, number2)
	fmt.Println(result, number1, number2) // 7 7 3
	println(result, number1, number2)     // 0x14000132000 0x14000132000 0x14000132020
}

亦或

Xor方法进行亦或运算:

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number1 := big.NewInt(5)
	number2 := big.NewInt(3)

	// Same as 5 ^ 3
	result := number1.Xor(number1, number2)
	fmt.Println(result, number1, number2) // 6 6 3
	println(result, number1, number2)     // 0x14000132000 0x14000132000 0x14000132020
}

Not方法进行非运算:

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number := big.NewInt(7)
	result := number.Not(number)
	fmt.Println(result, number) // -8, -8
	println(result, number)     // 0x14000132000 0x14000132000
}

按位清除

c = a &^ b

b转换为二进制后,值为1的位置对应c的位置为0,c中剩余比特值与a对应位置的比特值相等。

例如 0110 &^ 1011 = 0100

在big.Int实例中,提供了AndNot方法来执行按位清除运算:

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number1 := big.NewInt(5)
	number2 := big.NewInt(11)

	// Same as 5 &^ 11
	result := number1.AndNot(number1, number2)
	fmt.Println(result, number1, number2) // 4 4 11
	println(result, number1, number2)     // 0x14000132000 0x14000132000 0x14000132020
}

开方

Sqrt方法提供了开方运算,并返回结果的绝对值。其返回值也是一个big.Int实例:

package main

import (
   "fmt"
   "math/big"
)

func main() {
   number := big.NewInt(9)
   result := number.Sqrt(number)
   fmt.Println(result, number) // 3 3
   println(result, number)     // 0x14000128000 0x14000128000
}

如果被开方的结果不能用一个整数来表示,那么Sqrt方法返回一个最接近该值的整数。因此在涉及高精度计算时,不建议采用Sqrt方法。

package main

import (
   "fmt"
   "math/big"
)

func main() {
   number := big.NewInt(7)
   result := number.Sqrt(number)
   fmt.Println(result, number) // 2 2
   println(result, number)     // 0x14000128000 0x14000128000
}

如果被开方的数字是个负数,那么panic会被抛出:

package main

import (
   "fmt"
   "math/big"
)

func main() {
   number := big.NewInt(-9)  // panic: square root of negative number
   result := number.Sqrt(number)
   fmt.Println(result, number)
   println(result, number)
}

类型转换

big.Int提供了一些类型转换的API,可供使用者将big.Int实例转换成期望的结果。

string

可使用String方法或fmt包中的格式化函数将big.Int转换成字符串:

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number := big.NewInt(531)

	numberString := number.String()
	fmt.Println(numberString)
	// 531

	numberString = fmt.Sprint(number)
	fmt.Println(numberString)
	// 531
}

int64

Int64方法将big.Int实例转换为int64整数。

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number := big.NewInt(531)

	number64 := number.Int64()
	fmt.Println(number64)
	// 531
}

如果big.Int表示的数据超出int64的最大范围(-9223372036854775808 ~ 9223372036854775807),转换的结果是不准确的。

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number, ok := new(big.Int).SetString("9223372036854775809", 10)
	if !ok {
		fmt.Println("create big.Int failed")
		return
	}

	number64 := number.Int64()
	fmt.Println(number64)
	// -9223372036854775807
}

为了避免这种情况的发生,我们可以使用IsInt64方法判断big.Int实例是否可以正确转换成int64:

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number, ok := new(big.Int).SetString("9223372036854775809", 10)
	if !ok {
		fmt.Println("create big.Int failed")
		return
	}

	if !number.IsInt64() {
		fmt.Println("can not be represented as an int64")
		return
	}
	
	// ...
}

uint64

big.Int提供了Uint64和IsUint64方法,用来将big.Int实例转换为uint64类型和判断是否可以转换。其用法与Int64和IsInt64类似,这里不再赘述。

[]byte

使用Bytes方法将big.Int实例的绝对值转换为[]byte:

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number1 := big.NewInt(512)
	fmt.Println(number1.Bytes())
	// [2 0]

	number2 := big.NewInt(-512)
	fmt.Println(number2.Bytes())
	// [2 0]
}

其它

获取比特数

BitLen方法返回一个int数值表示big.Int实例绝对值的比特长度:

package main

import (
	"fmt"
	"math/big"
)

func main() {
	number := big.NewInt(8)
	fmt.Println(number.BitLen()) // 4
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值