GO语言入门:常用数学函数2

打印 上一主题 下一主题

主题 1681|帖子 1681|积分 5043

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
14.6 大型数值

math/big 包中公开了一些实用 API,用于表示大型整数值和浮点数值。当底子类型无法容纳要使用的数值时,应改用 big 包中提供的新类型。比方 Int、Float 等。
14.6.1 大型整数值之间的运算

若盼望让下面两个整数值完成加、减法运算,如许编写代码会发生错误。
  1. var (
  2.     a uint64 = 8000006554217002143024
  3.     b uint64 = 6676225236988563328930
  4. )
  5. c1 := a + b
  6. c2 := a - b
  7. fmt.Printf("%d + %d = %d\n", a, b, c1)
  8. fmt.Printf("%d - %d = %d\n", a, b, c2)
复制代码
运行步伐会得到如下的错误信息:
  1. constant 8000006554217002143024 overflows uint64
  2. constant 6676225236988563328930 overflows uint64
复制代码
原因是数值太大,已经凌驾uint64类型的有效范围。
解决方案只能使用 big 包中的 Int 类型。下面的代码将重新实现上述两个整数举行加、减运算的功能。
  1. // 两个整数值的字符串形式
  2. var (
  3.     num1 = "8000006554217002143024"
  4.     num2 = "6676225236988563328930"
  5. )
  6. // 实例化 Int 对象,使用指针类型(*Int)
  7. var bigInt1 = new(big.Int)
  8. var bigInt2 = new(big.Int)
  9. // 将两个字符串表示的值设置到 Int 对象中
  10. bigInt1.SetString(num1, 10)
  11. bigInt2.SetString(num2, 10)
  12. // 进行加法运算
  13. var res1 = new(big.Int)
  14. res1.Add(bigInt1, bigInt2)
  15. fmt.Printf("%d + %d = %d\n", bigInt1, bigInt2, res1)
  16. // 进行减法运算
  17. var res2 = new(big.Int)
  18. res2.Sub(bigInt1, bigInt2)
  19. fmt.Printf("%d - %d = %d\n", bigInt1, bigInt2, res2)
复制代码
由于底子的整数类型(比方 int64、uint64)均无法容纳两个大型整数值,所以只能用字符串来表示。
  1. num1 = "8000006554217002143024"
  2. num2 = "6676225236988563328930"
复制代码
然后,调用 Int 实例的 SetString 方法将整数值设置到 Int 实例中。如果要设置的值未超出底子类型的有效范围,是可以使用 SetInt64 和 SetUint64 方法的。
两个大型整数值举行加减运算后,其结果也是大型数值,因此也需要使用 Int 对象来存储盘算结果。加法运算调用 Add 方法,减法运算调用Sub方法。
  1. res1.Add(bigInt1, bigInt2)
  2. res2.Sub(bigInt1, bigInt2)
复制代码
运行上述步伐,将得到以下盘算结果:
  1. 8000006554217002143024 + 6676225236988563328930 = 14676231791205565471954
  2. 8000006554217002143024 - 6676225236988563328930 = 1323781317228438814094
复制代码
big 包中的类型对象一般会使用指针类型(如 *Int、 *Float 等)。一方面,指针类型仅引用对象的地址,包管在调用各种方法(如上面用到的 Add 方法)过程中所传递的都是唯一的实例;另一方面,这些类型实例存储的数值很大,占用内存空间也比较多,不适宜频繁复制(非指针类型变量在赋值时会复制对象,而指针类型变量仅复制对象的内存地址)。
14.6.2 阶乘运算

阶乘的盘算结果往往较大,极有可能超出底子整数类型的范围,因此使用big.Int类型来存储阶乘运算的结果较为合适。
big.Int 类型是可以直接举行阶乘运算的,因为它有一个名为 MulRange 的方法,其签名如下:
  1. func MulRange(a int64, b int64) *Int
复制代码
它的功能是产生[a, b]范围内的所有整数的积(包含 a 和 b)。运用这个方法便可以轻松完成阶乘运算,即将求积的整数范围设定在 [1, n] 或 [2, n]。比方,要求 5 的阶乘,可以如许调用方法:
  1. MulRange(1, 5)
  2. 或者
  3. MulRange(2, 5)
复制代码
下面的示例分别求 30 和 50 的阶乘。
  1. var c = new(big.Int)
  2. // 求 30 的阶乘
  3. c.MulRange(1, 30)
  4. fmt.Printf("30! = %d\n", c)
  5. // 求 50 的阶乘
  6. c.MulRange(1, 50)
  7. fmt.Printf("50! = %d\n", c)
复制代码
盘算结果如下:
  1. 30! = 265252859812191058636308480000000
  2. 50! = 304140932017133780436126081660647688443776415689605120000000000000
复制代码
14.6.3 使用大型浮点数值

big 包中的 Float 类型与 Int 类型相似,专用于存储大型的浮点数值。
下面的代码将创建 Float 对象,并设置一个大型的浮点数值。
  1. var strfloat = "0.001234567890234567893456789"
  2. var bigFloat = new(big.Float)
  3. // 设置精度
  4. bigFloat.SetPrec(50)
  5. // 设置浮点数值
  6. bigFloat.SetString(strfloat)
  7. // 打印到屏幕上
  8. fmt.Printf("%.50f\n", bigFloat)
复制代码
SetPrec 方法用来设置浮点数值的精度,上述代码中设置为 50。随后调用 SetString 方法将字符串表示的浮点数设置到 Float 对象中。
浮点数值打印结果如下:
  1. 0.00123456789023456726950289663591320277191698551178
复制代码
由于二进制运算存在误差,打印出来的数值与原值会有差别。
Float 结构体还定义了一些可举行常见运算的方法。比方,Add 方法支持加法运算,Sub 方法支持减法运算。
下面的示例将演示大型浮点数值的四则运算。
步调 1:定义两个 float64 类型的变量,作为 Float 对象的原始数值。
  1. var (
  2.     a float64 = 1550.797220660354896132160489549963189232654585896489465456159657
  3.     b float64 = 0.0016200166894105953690156
  4. )
复制代码
步调 2:创建三个 Float 对象实例。
  1. var (
  2.     bigFa = new(big.Float)
  3.     bigFb = new(big.Float)
  4.     bigRes = new(big.Float) // 存放计算结果
  5. )
复制代码
步调 3:设置精度。
  1. bigFa.SetPrec(100)
  2. bigFb.SetPrec(100)
  3. bigRes.SetPrec(100)
复制代码
步调 4:设置原始数值。
  1. bigFa.SetFloat64(a)
  2. bigFb.SetFloat64(b)
复制代码
如果数值很大,凌驾了float64类型的可容纳范围,则可以使用字符串来表示数值,再调用 SetString 方法来设置。
步调 5:完成四则运算。
  1. // 加
  2. bigRes.Add(bigFa, bigFb)
  3. fmt.Printf("%.15f + %.15f = %.15f\n", bigFa, bigFb, bigRes)
  4. // 减
  5. bigRes.Sub(bigFa, bigFb)
  6. fmt.Printf("%.15f - %.15f = %.15f\n", bigFa, bigFb, bigRes)
  7. // 乘
  8. bigRes.Mul(bigFa, bigFb)
  9. fmt.Printf("%.15f * %.15f = %.15f\n", bigFa, bigFb, bigRes)
  10. // 除
  11. bigRes.Quo(bigFa, bigFb)
  12. fmt.Printf("%.15f / %.15f = %.15f\n", bigFa, bigFb, bigRes)
复制代码
步调 6:运行示例,结果如下所示:
  1. 1550.797220660354924 + 0.001620016689411 = 1550.798840677044334
  2. 1550.797220660354924 - 0.001620016689411 = 1550.795600643665513
  3. 1550.797220660354924 * 0.001620016689411 = 2.512317379361341
  4. 1550.797220660354924 / 0.001620016689411 = 957272.373054734186086
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

何小豆儿在此

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表