【问题标题】:How can I declare a float-typed Go constant of arbitrary bit pattern?如何声明任意位模式的浮点型 Go 常量?
【发布时间】:2017-06-13 14:44:54
【问题描述】:

在 Go 中,我可以像这样声明一个类型化的浮点常量:

const foo float64 = 1e100

或像这样的任意位模式的浮点变量:

var bar = math.Float64frombits(0x7ff8c0c0ac0ffee1)

但这是一个错误(“const initializer… is not a constant”):

const baz = math.Float64frombits(0x7ff8c0c0ac0ffee1)

如何声明任意位模式的类型化 float const?

【问题讨论】:

  • 您可以将其存储为uint64 常量并按需转换(这就是数学包内部的操作方式)
  • 这实际上是一个很好的建议。导出值(例如用作标记值的值)有点烦人,因为依赖包也需要导入 math,但至少它确保了常量性。

标签: go floating-point bit-manipulation constants


【解决方案1】:

如果你想存储位值(本质上是一个uint64),并将它作为float64 提供给外部包,你可以提供一个“常量”函数,你保证只返回恒定值。这正是math.NaN 等函数的工作原理。

const uintFoo = 0x7ff8c0c0ac0ffee1

func ConstFoo() float64 {
    return math.Float64frombits(uintFoo)
}

【讨论】:

    【解决方案2】:

    您对 Math.Float64frombits 的调用发生在运行时,而不是编译时,因此不是常量。从有效的 Go 页面(这将比我更好地解释它):

    Go 中的常量就是常量。它们是在编译时创建的 时间,即使在函数中定义为局部变量,也只能是 数字、字符串或布尔值。由于编译时的限制, 定义它们的表达式必须是常量表达式, 可由编译器评估。例如,1

    链接:https://golang.org/doc/effective_go.html#constants

    【讨论】:

    • 我明白这一点。但它没有回答这个问题。 (我认为这个问题的答案可能是“提交一个 go 语言更改提案”,但我想确保在我这样做之前我没有错过任何东西。)
    【解决方案3】:

    你不能在常量声明中调用像Float64frombits 这样的函数;函数调用意味着它不能在编译时完全评估,所以它不能用作常量。但是,您可以将位转储为浮点值:

    const myFloat float64 = 0x7ff8c0c0ac0ffee1
    
    func main() {
        fmt.Println(myFloat)
    }
    

    【讨论】:

    • 这不会将按位表示应用于float64,它本质上是float64(0x7ff8c0c0ac0ffee1)
    • 是的,没错。问题没有具体说明他们对输入输出的期望的详细信息,因此我给出了从任意十六进制值设置 const 值的唯一可用选项。
    • 该问题指定的结果等同于Float64frombits。将任意十六进制值数字转换为 float64 与将 uint64 位解释为 float64 不同。
    • 根据值,可以使用适当的十六进制值使其等效。很难说,因为问题的示例math.Float64frombits(0x7ff8c0c0ac0ffee1) 返回NaN
    • 这是重点的一部分,这些位以 NaN 掩码值开头,不能写为 float64 文字。更不用说由于十六进制文字只能是整数值,它们代表可能的 float64 值的很小一部分,因此只能在非常有限的意义上进行近似。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多