【问题标题】:Different pattern using the same float constant values leads to different results [duplicate]使用相同浮点常量值的不同模式会导致不同的结果[重复]
【发布时间】:2019-08-13 09:54:40
【问题描述】:

在以下 go 代码的 sn-p 中,我很难理解为什么结果不同:

func main() {
    a := -0.2; b := -0.1; 
    fmt.Println(a+b)
    //Outputs expected float value with rounding error  : -0.30000000000000004
    c := (-0.2)+(-0.1)
    fmt.Println(c)
    //Will ouput -0.3 (the actual exact constant).
}

究竟发生了什么,当这些常量不用于实例化浮点数时,go 是否以某种方式将 c 操作作为常量而不是 float64 操作执行? 完整版:https://play.golang.org/p/kUICDGFiMvf

任何见解都将不胜感激,谢谢。

【问题讨论】:

  • 很可能是因为在第二种情况下,编译器会在编译期间计算结果。这是一个非常常见的优化。无论如何,舍入误差出现在 second 情况下,而不是第一种情况。编译器在生成赋值操作之前对结果进行四舍五入。像 0.10.20.3 0.3 can't be represented accuratelly 这样的数字使用浮点数
  • 0.30000000000000004.com 第一部分和第二部分:阅读 Go 如何处理常量:它们(几乎)是任意精度。
  • 另外fmt.Println() 执行一些舍入,如果你像fmt.Printf("%.20f", c) 一样打印它,你会看到-0.29999999999999998890 的结果。
  • Playground 使用遵循 Go 语言规范的普通 Go 编译器。所以是的,(-0.2)+(-0.1) 在编译期间被评估为 -0.3,并且该值被分配给 c。一切都按照语言规范 100% 完成。当您说“而不是遵循正常的浮动操作流程”时,您是什么意思。除了语言规范所说的之外,什么是“正常的浮动操作”?
  • golang.org/ref/spec#Constant_expressions 规范简短,可读且可搜索:“const”的前三个搜索结果都是目录中的相关条目。 Go 确实不同于其他语言。在大多数语言中,您必须咨询专家,在 Go 中您可以搜索规范,这通常更快。

标签: go floating-point ieee-754


【解决方案1】:

我尝试使用java,结果是

public class StringTest {
    public static void main(String[] args) {

        double a = -0.2;
        double b = -0.1;
        System.out.println(a + b);
       //  -0.30000000000000004

        double c = a + b;
        System.out.println(c);
      // -0.30000000000000004

    }
}

似乎任何使用二进制浮点数的编程语言都会有这个问题。某些语言的 Number 类型使用 IEEE754 标准来表示数字。 还有什么是IEEE-745 float,可以看it

【讨论】:

  • Go 的常量求值规则与大多数其他主流编程语言的规则完全不同。 Java 中发生的事情对于理解 OP 的 Go 示例中发生的事情并没有真正有用。
  • 是的,我只是举个例子
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多