除以零不会panic?

本文详细探讨了Go语言中除以常量0、整型0和浮点数0的不同行为,其中除以常量0无法编译,除以整型0会导致panic,而除以浮点数0则可能得到正无穷(+Inf)、负无穷(-Inf)或NaN。对于±Inf和NaN,文章介绍了如何判断和比较它们,并提供了相关函数的使用示例。最后,强调了在实际开发中处理边界值的重要性,特别是涉及除以零的情况。
摘要由CSDN通过智能技术生成

有常识的人都知道,在除法运算中不能除以零,而我们在实际的应用中面对大量的上下文,很有可能因为考虑不周就出现除以零的情况。因此,我们有必要知道除以零到底会不会panic?如果不发生panic,又会得到什么样的值?

下面,我们带着这样的疑问继续阅读本文。相信在读完本文后,这两个疑问会烟消云散。同时,为了能够让读者快速地了解本文的全貌,下面列出本文的大纲。

c84a18a24a2148389f5911f9c7a29b48.png

除以零值

在Go中,可能除以零的情况分为三种,分别是除以常量0、整形0和浮点数0。下面我们分别看一下这三种情况的实际表现。

除以常量0

edd1e3417b4d0f571134efc30098f1c8.png

根据上图知道,除以常量0是无法编译通过的。这一点,还是比较令人安心。

除以整形0

b15b6ec6645558768d04150c96462851.png

根据上图知,除以整形0会发生panic。这一点,在平时的开发中还需格外注意。

除以浮点数0

除以浮点数0,情况会略微复杂。请看下代码和输出结果。

var zero = float64(0)
fmt.Println(1024 / zero) // 输出:+Inf
fmt.Println(-1024 / zero) // 输出:-Inf
fmt.Println(0 / zero) // NaN

上面输出中Inf为单词infinity的缩写,该单词含义为无穷,因此+Inf-Inf分别表示正无穷和负无穷。

NaN意味着not a number,即结果不是一个数。

到这里,老许不得不感叹浮点数确实博大精深,在Go里面除以0确实不会panic(经过老许验证,在python里面会发生错误)。另外,上述中0/zero得到NaN,而整形中0除以0依旧会panic。

±Inf值

判断是否是±Inf

前面通过正数和负数分别除以浮点数0可到正无穷和负无穷。Go里面math包提供的Inf函数也可以得到正无穷和负无穷,同时还提供了IsInf函数用于判断是正无穷还是负无穷。

math.Inf函数签名为func(int) float64,当传入的参数大于等于0时返回正无穷,否则返回负无穷。

math.IsInf函数签名为func(float64, int) bool,第一个参数为待判断的值,第二个参数大于0时,返回第一个参数是否为正无穷,第二个参数小于0时,返回第一个参数是否为负无穷,第二个参数等于0时,返回第一个参数是否为无穷。

具体验证,请看下面代码和输出。

positiveInf := math.Inf(1)
negativeInf := math.Inf(-1)
// 判断是否为正无穷
fmt.Println(math.IsInf(positiveInf, 1)) // 输出:true
// 判断是否为负无穷
fmt.Println(math.IsInf(negativeInf, 1)) // 输出:false
// 判断是否为正无穷
fmt.Println(math.IsInf(positiveInf, -1)) // 输出:false
// 判断是否为负无穷
fmt.Println(math.IsInf(negativeInf, -1)) // 输出:true
// 判断是否为无穷
fmt.Println(math.IsInf(positiveInf, 0)) // 输出:true
// 判断是否为无穷
fmt.Println(math.IsInf(negativeInf, 0)) // 输出:true
// 判断是否为无穷
fmt.Println(math.IsInf(1024, 0)) // 输出:false

±Inf的比较

正无穷和负无穷输出结果和我们平时看到数值类型迥然不同,而且也无法直接将±Inf直接赋值给一个浮点类型的变量,那么他们是否可以参与数值之间的比较呢,请看下面代码和输出。

positiveInf := math.Inf(1)
negativeInf := math.Inf(-1)
// 判断正无穷是否可以和自身比较
fmt.Println(positiveInf == positiveInf) // 输出:true
// 判断负无穷是否可以和自身比较
fmt.Println(negativeInf == negativeInf) // 输出:true
// 判断正无穷是否大于正数
fmt.Println(positiveInf > math.MaxFloat64) // 输出:true
// 判断负无穷是否小于正数
fmt.Println(negativeInf < -math.MaxFloat64) // 输出:true

根据输出结果知,正负无穷可以比较,且表示的值确实暗合无穷这一数学意义。

NaN值

判断是否是NaN

在这里加深一下生成NaN值的印象,浮点数零相除即可得到NaN值。同样,math包提供了NaN函数和IsNaN函数分别用于返回一个NaN值和判断一个浮点数是否为NaN

请看下面代码和输出。

nan := math.NaN()
fmt.Println(math.IsNaN(nan))  // 输出:true
fmt.Println(math.IsNaN(10.2)) // 输出:false

其他可生成NaN值的情况:

  1. 任何与NaN一起的运算结果都为NaN

  2. 如果x < -1 || x > 1,则math.Acos(x)math.Asin(x)math.Atanh(x)均返回NaN

  3. 如果x < 1,则math.Acosh(x)返回NaN

  4. 如果x < 0,则math.Sqrt(x)返回NaN

应该还有其他返回NaN的情况,老许就不一一总结了。

NaN的比较

根据静态检查的提示“no value is equal to NaN, not even NaN itself”,没有值等于NaN甚至于它自己都不是它自己。为了做更进一步的验证,我们看下面代码和输出。

nan := math.NaN()
positiveInf := math.Inf(1)
negativeInf := math.Inf(-1)
fmt.Println(nan == nan)

fmt.Println(nan > 1024) // 输出:false
fmt.Println(nan < 1024) // 输出:false
fmt.Println(nan == 1024) // 输出:false
fmt.Println(nan > positiveInf) // 输出:false
fmt.Println(nan < negativeInf) // 输出:false
fmt.Println(nan == positiveInf) // 输出:false
fmt.Println(nan == negativeInf) // 输出:false

确实,如提示所说,NaN不等于它自己,且它和任何值比较时都为false。由于NaN的特殊性,所以在实际开发中我们一定要注意边界值的处理。

写在最后

本文主要讲解了除以常量0、整形0和浮点数0的各种情况,以及对±InfNaN的可比性做了分析。下面是一张各种值是否可比的对照表。

是否可比+Inf-InfNaNNumber
+InfYYNY
-InfYYNY
NanNNNN
NumberYYNY

这里说的不可比主要指NaN和任何值比较都返回false

最后,衷心希望本文能够对各位读者有一定的帮助。

推荐阅读:

深度细节 | Go 的 panic 的秘密都在这

资料下载

点击下方卡片关注公众号,发送特定关键字获取对应精品资料!

  • 回复「电子书」,获取入门、进阶 Go 语言必看书籍。

  • 回复「视频」,获取价值 5000 大洋的视频资料,内含实战项目(不外传)!

  • 回复「路线」,获取最新版 Go 知识图谱及学习、成长路线图。

  • 回复「面试题」,获取四哥精编的 Go 语言面试题,含解析。

  • 回复「后台」,获取后台开发必看 10 本书籍。

对了,看完文章,记得点击下方的卡片。关注我哦~ 👇👇👇

如果您的朋友也在学习 Go 语言,相信这篇文章对 TA 有帮助,欢迎转发分享给 TA,非常感谢!ce8e9ed86019402dec1e31d92d37d4a2.png

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值