在日常的开发过程中,不可避免的需要使用到超过变量类型的数值计算,在 go 语言中,int64 类型的变量的储存范围是
-9223372036854775808 ~ 9223372036854775807,当我们需要计算的数值大于这个范围之后,计算出的结果就会出错,这时候就需要使用到
go 语言中专门为大数计算而存在的标准库:math/big 包里面的内容。
比如
package main
import (
"fmt"
"math"
)
func main() {
a := math.MaxInt64
b := math.MaxInt64
c := a + b
fmt.Printf("%d + %d = %d", a, b, c)
}
可以看出两个最大值的相加结果异常,这是因为两个最大值相加的结果超出了 int64 能够存储的范围。
math/big
如果需要进行上面这样的大数计算,可以使用 go 语言自带的 math/big 包进行计算,big 包中包含了整形 int 和浮点型 float 的大数计算。
package main
import (
"fmt"
"math"
"math/big"
)
func main() {
a := big.NewInt(math.MaxInt64)
b := big.NewInt(math.MaxInt64)
result := a.Add(a, b)
fmt.Println(result)
}
这样就可以相加了!
从字符串生成超大数字
package main
import (
"fmt"
"math/big"
)
func main() {
a := big.NewInt(1)
big1, ok := a.SetString("23431241234123412341324123412341234123434123432431241234132412341234123431241234", 10)
if !ok {
fmt.Println("设置失败")
}
fmt.Println(big1)
}
浮点数
大有理数 big.Rat 类型
大有理数的 big.Rat 类型
big.Rat
是Go语言 math/big
包中的一个类型,用于表示任意精度的有理数(即分数形式的数,如 ,其中 是分子, 是非零分母)。以下从多个方面对其进行介绍:
1. 创建 big.Rat
对象
- 使用
big.NewRat
函数:
该函数接受两个int64
类型的参数,分别为分子和分母,返回一个指向big.Rat
对象的指针。例如:
package main
import (
"fmt"
"math/big"
)
func main() {
rat := big.NewRat(3, 4)
fmt.Println(rat)
}
此代码创建了有理数 并输出。
- 使用
SetFrac
方法:
该方法可用于设置big.Rat
对象的分子和分母,接受两个big.Int
类型的参数。这在处理大整数作为分子或分母时非常有用。例如:
package main
import (
"fmt"
"math/big"
)
func main() {
num := big.NewInt(12345678901234567890)
den := big.NewInt(98765432109876543210)
rat := new(big.Rat).SetFrac(num, den)
fmt.Println(rat)
}
2. 约分
big.Rat
对象在创建时会自动进行约分。例如,创建 时,实际存储的是约分后的 。这确保了有理数以最简形式表示,方便后续计算和比较。
3. 基本运算
- 加法:使用
Add
方法,将两个big.Rat
对象相加。例如:
package main
import (
"fmt"
"math/big"
)
func main() {
rat1 := big.NewRat(1, 2)
rat2 := big.NewRat(1, 3)
result := new(big.Rat).Add(rat1, rat2)
fmt.Println(result)
}
这里计算 。
- 减法:通过
Sub
方法实现。例如:
package main
import (
"fmt"
"math/big"
)
func main() {
rat1 := big.NewRat(3, 4)
rat2 := big.NewRat(1, 4)
result := new(big.Rat).Sub(rat1, rat2)
fmt.Println(result)
}
即 (自动约分)。
- 乘法:使用
Mul
方法。例如:
package main
import (
"fmt"
"math/big"
)
func main() {
rat1 := big.NewRat(2, 3)
rat2 := big.NewRat(3, 5)
result := new(big.Rat).Mul(rat1, rat2)
fmt.Println(result)
}
计算 。
- 除法:通过
Quo
方法进行。例如:
package main
import (
"fmt"
"math/big"
)
func main() {
rat1 := big.NewRat(4, 5)
rat2 := big.NewRat(2, 3)
result := new(big.Rat).Quo(rat1, rat2)
fmt.Println(result)
}
即 。
4. 比较
Cmp
方法:用于比较两个big.Rat
对象的大小。返回值为-1
(表示第一个数小于第二个数)、0
(表示两个数相等)或1
(表示第一个数大于第二个数)。例如:
package main
import (
"fmt"
"math/big"
)
func main() {
rat1 := big.NewRat(1, 2)
rat2 := big.NewRat(3, 4)
cmp := rat1.Cmp(rat2)
if cmp == -1 {
fmt.Println("rat1 小于 rat2")
} else if cmp == 0 {
fmt.Println("rat1 等于 rat2")
} else {
fmt.Println("rat1 大于 rat2")
}
}
5. 转换
- 转换为浮点数:
Float64
方法将big.Rat
对象转换为float64
类型的值。需要注意的是,由于float64
精度有限,可能会丢失精度。例如:
package main
import (
"fmt"
"math/big"
)
func main() {
rat := big.NewRat(1, 3)
f := rat.Float64()
fmt.Printf("%.10f\n", f)
}
这里将 转换为 float64
,输出结果会有一定精度损失。
- 转换为字符串:
String
方法将big.Rat
对象转换为字符串形式,格式为分子/分母
。例如:
package main
import (
"fmt"
"math/big"
)
func main() {
rat := big.NewRat(5, 7)
s := rat.String()
fmt.Println(s)
}
big.Rat
类型在需要精确表示和计算有理数的场景中非常有用,如金融计算、科学计算等领域,避免了浮点数运算可能带来的精度问题。