阿小信大人的头像
Where there is a Python, there is a way. 阿小信大人

Golang 运行时的除数为0的情况返回Inf2021-11-21 14:46

在Golang中,除数为0时,常规情况下是无法编译通过的,但是如果除数是由运行时决定的,那么为除数为0时则不会panic,而是实现为IEEE 754标准,返回Inf。

The result of a floating-point or complex division by zero is not specified beyond the IEEE-754 standard; whether a run-time panic occurs is implementation-specific.

IEEE 754 specifies five arithmetic exceptions that are to be recorded in the status flags ("sticky bits"):

inexact, set if the rounded (and returned) value is different from the mathematically exact result of the operation. underflow, set if the rounded value is tiny (as specified in IEEE 754) and inexact (or maybe limited to if it has denormalization loss, as per the 1984 version of IEEE 754), returning a subnormal value including the zeros. overflow, set if the absolute value of the rounded value is too large to be represented. An infinity or maximal finite value is returned, depending on which rounding is used. divide-by-zero, set if the result is infinite given finite operands, returning an infinity, either +∞ or −∞. invalid, set if a real-valued result cannot be returned e.g. sqrt(−1) or 0/0, returning a quiet NaN.

这种情况可能导致的问题是:如果结构体中的字段是由运行时算出为Inf,当你对这个结构体进行json序列化时,json Marshal 会返回错误:

json: unsupported value: +Inf

通过一段代码说明:

package main

import (
    "encoding/json"
    "fmt"
    "strconv"
)

func interfaceToFloat64(unk interface{}) (result float64) {
    switch i := unk.(type) {
    case float64:
        result = float64(i)
    case float32:
        result = float64(i)
    case int64:
        result = float64(i)
    case int32:
        result = float64(i)
    case int:
        result = float64(i)
    case uint32:
        result = float64(i)
    case uint64:
        result = float64(i)
    case uint:
        result = float64(i)
    case string:
        if i == "" || i == "--" {
            result = 0.0
        } else {
            result, _ = strconv.ParseFloat(i, 64)

        }
    default:
        result = 0.0
    }

    return
}

func main() {
    var (
        a interface{} = 1
        b interface{} = 0
    )

    x := interfaceToFloat64(a) / interfaceToFloat64(b)
    fmt.Println("x:", x)

    type T struct {
        F float64
    }
    t := T{
        F: x,
    }
    fmt.Printf("t: %+v\n", t)

    _, err := json.Marshal(t)
    fmt.Println("err:", err)

}

运行后输出结果:

x: +Inf
t: {F:+Inf}
err: json: unsupported value: +Inf

参考文档:

对于json序列化Inf失败的解决方法可以判断其是否为Inf,将其设为特定值来解决,如:

//  runtime 1.0 / 0.0 is +Inf
if math.IsNaN(x) || math.IsInf(x, 0) {
    x = 0.0
}

如果您觉得从我的分享中得到了帮助,并且希望我的博客持续发展下去,请点击支付宝捐赠,谢谢!

若非特别声明,文章均为阿小信的个人笔记,转载请注明出处。文章如有侵权内容,请联系我,我会及时删除。

#Golang#   阅读[96] 评论[0]

你可能也感兴趣的文章推荐

本文最近访客

网友157.*.*.177[Redmond]2021-12-05 09:45
网友157.*.*.70[Redmond]2021-12-05 09:40
网友66.*.*.52[火星]2021-12-05 09:31
网友216.*.*.226[Seattle]2021-12-05 09:30

发表评论