fmt.Printf中包含%g的宽度和精度字段的行为意外

时间:2016-04-06 23:25:23

标签: go printf

我正在尝试使用fmt.Printf()来获取一些使用相同宽度格式化的浮点数。

例如,给定浮点值0.0606060606060606,0.3333333333333333,0.05,0.4和0.1818181818181818,我想将每个值格式化为10符文:

0.06060606
0.33333333
      0.05
       0.4
0.18181818

但我无法理解它是如何完成的。文档说明

  

对于浮点值,width设置字段的最小宽度   和precision设置小数点后的位数,if   适当的,除了对于%g /%G,它设置总位数。   例如,给定123.45格式%6.2f打印123.45而%.4g   打印123.5。 %e和%f的默认精度为6;对于%g它是   标识值所需的最小位数   唯一地

因此,如果我使用%f,则较大的数字将不适合10个字符的约束,因此需要%g。要获得最小宽度10为%10g并获得最多9位数(点数为+1),%.9g,但在%10.9g中合并它们是没有像我期望的那样行事

0.0606060606
0.333333333
      0.05
       0.4
0.181818182

为什么我得到10符文的字符串,其他符号为11符文,其他符号为12符文?

特别是,%.9g似乎总共不会产生9位数字。例如,请参阅:http://play.golang.org/p/ie9k8bYC7r

2 个答案:

答案 0 :(得分:1)

是的,我同意:它优先考虑"精确字段"不要"宽度"。 因此,当我们需要修复列进行打印时,我们需要编写新的格式化函数。

答案 1 :(得分:1)

首先,我们需要正确理解文档:

  

width设置字段的最小宽度,精度设置小数点后的位数(如果适用),但%g /%G除外,它设置总位数。

这一行在语法上是正确的,但在这句话的最后部分真的令人困惑:它实际上是指精度,而不是宽度

因此,让我们看一些例子:

123.45
12312.2
1.6069
0.6069
0.0006069

并按照fmt.Printf("%.4g")打印,它会为您提供

123.5
1.231e+04
1.607
0.6069
0.0006069

只有4个数字,不包括所有小数点和指数。但等等,最后两个例子会发生什么?你开玩笑的我不是超过5位吗?

这是打印中令人困惑的部分:前导0 不会被计为数字,在少于4个零时不会缩小。< / p>

让我们看一下使用以下示例的0行为:

package main

import "fmt"

func main() {
    fmt.Printf("%.4g\n", 0.12345)
    fmt.Printf("%.4g\n", 0.012345)
    fmt.Printf("%.4g\n", 0.0012345)
    fmt.Printf("%.4g\n", 0.00012345)
    fmt.Printf("%.4g\n", 0.000012345)
    fmt.Printf("%.4g\n", 0.0000012345)
    fmt.Printf("%.4g\n", 0.00000012345)

    fmt.Printf("%g\n", 0.12345)
    fmt.Printf("%g\n", 0.012345)
    fmt.Printf("%g\n", 0.0012345)
    fmt.Printf("%g\n", 0.00012345)
    fmt.Printf("%g\n", 0.000012345)
    fmt.Printf("%g\n", 0.0000012345)
    fmt.Printf("%g\n", 0.00000012345)
}

和输出:

0.1235
0.01235
0.001234
0.0001234
1.234e-05
1.234e-06
1.235e-07
0.12345
0.012345
0.0012345
0.00012345
1.2345e-05
1.2345e-06
1.2345e-07

所以你可以看到,当少于4个前导0时,它们将被计算在内,并且如果有更多则会缩小。

好的,接下来就是width。从文档中,width仅指定最小宽度,包括小数位和指数。这意味着,如果您的位数超过指定的width,则会突出宽度。

请记住,宽度将被视为最后一步,这意味着它需要首先满足精度字段

让我们回到你的案子。您指定了%10.9g,这意味着您希望总数为9,不包括前导0,最小宽度为10,包括小数位和指数,并且精度应该优先。

0.0606060606060606:取9位而不带前导0会给你0.0606060606,因为它已经是12宽度,它通过最小宽度为10;

0.3333333333333333:取9位而不带前导0会给你0.333333333,因为它已经是11宽度,它通过最小宽度为10;

0.05:取9个数字,不带前导0会给你0.05,因为它小于宽度10,它将填充另外6个宽度以获得10的宽度;

0.4:与上述相同;

0.1818181818181818:取9位而不带前导0会给你0.181818182 舍入,因为它已经是11宽度,它会超过最小宽度10。

所以这就解释了为什么你得到了有趣的印刷品。