Golang中的负零字面量

11

IEEE754 支持负零,但这段代码

a  := -0.0
fmt.Println(a, 1/a)

输出

0 +Inf

在我预期的地方

-0 -Inf

其他以IEEE754为基础的浮点格式的语言允许您创建负零字面量。

Java:

float a = -0f;
System.out.printf("%f %f", a, 1/a); // outputs "-0,000000 -Infinity"

C# :

C#:
var a = -0d;
Console.WriteLine(1/a); // outputs "-Infinity"

Javascript :


JavaScript:
​var a = -0;
console.log(a, 1/a);​ // logs "0 -Infinity"

但是我在Go中找不到相应的等价物。

在Go中如何编写负零字面量?


2
你尝试过 a := 0.0; a *= -1.0 吗? - Daniel Fischer
1
你是否已经提交了关于Go的错误报告? - Stephen Canon
@StephenCanon 在提交之前我本来想问golang-nuts的。但实际上这并不需要:已经有一个注册的问题(请参见下面的“答案”)。 - Denys Séguret
不确定编译器是否已经如此智能,但是a := 0.0; -a这种情况可能是编译器能够将其优化为负零常量的最有可能的情况。这只比在语言中添加一个字面负零略微冗长。 - thomasrutter
请注意,该语言明确将-0.0定义为等同于0.0,因此在此阶段更改该定义是不可能的。 - thomasrutter
显示剩余4条评论
3个回答

11

这里有一个已注册的问题

并且恰好提供了一种解决方案:

a := math.Copysign(0, -1)

这并不那么糟糕,因为它显然是指由IEEE754定义的标准copysign函数。

但是这意味着你需要导入一个包,这看起来仍然太重了(尽管这种情况很少发生)。


不导入"math": http://play.golang.org/p/iymSJElses(我相信它被内联了) - zzzz
8
很不幸,根据问题页面的讨论,这似乎是指定的语言行为,因为它明显违反了IEEE-754(5.12.1)的规定:“从支持的格式转换为外部字符序列[包括源语言字面量]以及恢复原始浮点表示的转换,应该恢复零、无穷大和静默NaN,以及非零有限数字。特别地,零和无穷大的符号被保留。 - Stephen Canon

6
package main

import (
        "fmt"
        "math"
)

func main() {
        a := 1. / math.Inf(-1)
        fmt.Println(a, 1/a)
}

(还有 这里)


输出:

-0 -Inf

从数学上讲,-0和0是相等的,所以我猜Go做了正确的事情。据我所知,0的符号只是来自于下溢,而不是一元减号(如-1*0)。 - zzzz
1
请不要与JavaScript进行比较。JS因在数学方面犯了许多错误而闻名。 - JohnDoe
3
@jnml - 说 "+0 == -0" 并不完全正确,因为 "-0" 可能代表一个被舍入为零的小负数。请参考 http://en.wikipedia.org/wiki/Signed_zero。值得注意的是,Go 有声称正确处理 IEEE-754 并且这是其要求之一。 - Rick-777
从您提供的链接中可以得知:“根据IEEE 754标准,负零和正零应该与通常(数值)比较运算符相等,例如C和Java的==运算符。” - Denys Séguret
就比较运算符“==”而言,你说得很对。我的观点是,由于限制和舍入问题,IEEE-754需要区分+0和-0,以承认2s补码二进制浮点算术的轻微不精确性。 - Rick-777
显示剩余4条评论

0

我刚试了一下,对我来说似乎有效。

package main

import (
    "fmt"
    )

func main() {
    zero := float64(0)
    neg_zero := -zero
    fmt.Println(zero, neg_zero)
}

当我执行neg_zer0 := - float64(0)时,它并不像预期的那样工作。


这相当于我收到的第一条评论(来自Daniel Fischer)。那不是字面意思。 - Denys Séguret

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接