How to format floating point numbers into a string using Go

huangapple go评论171阅读模式
英文:

How to format floating point numbers into a string using Go

问题

使用Go语言,我正在尝试找到将浮点数格式化为字符串的“最佳”方法。我已经查找了一些示例,但没有找到能够明确回答我问题的内容。我只想使用“最佳”方法将浮点数格式化为字符串。小数位数可能会变化,但是会是已知的(例如2位、4位或零位)。

下面是我想要实现的一个示例。

基于下面的示例,我应该使用fmt.Sprintf()还是strconv.FormatFloat()或其他方法?

每个方法的常规用法和区别是什么?

我还不明白在下面的代码中使用32或64的意义,当前代码中使用的是32:

strconv.FormatFloat(float64(fResult), 'f', 2, 32)

示例代码:

package main

import (
    "fmt"
    "strconv"
)

func main() {

    var (
        fAmt1 float32 = 999.99
        fAmt2 float32 = 222.22
    )

    var fResult float32 = float32(int32(fAmt1*100) + int32(fAmt2*100)) / 100

    var sResult1 string = fmt.Sprintf("%.2f", fResult)

    println("Sprintf value = " + sResult1)

    var sResult2 string = strconv.FormatFloat(float64(fResult), 'f', 2, 32)

    println("FormatFloat value = " + sResult2)

}
英文:

Using Go I'm trying to find the "best" way to format a floating point number into a string. I've looked for examples however I cannot find anything that specifically answers the questions I have. All I want to do is use the "best" method to format a floating point number into a string. The number of decimal places may vary but will be known (eg. 2 or 4 or zero).
An example of what I want to achieve is below.

Based on the example below should I use fmt.Sprintf() or strconv.FormatFloat() or something else?

And, what is the normal usage of each and differences between each?

I also don't understand the significance of using either 32 or 64 in the following which currently has 32:

strconv.FormatFloat(float64(fResult), 'f', 2, 32)

Example:

package main

import (
    "fmt"
    "strconv"
)

func main() {

    var (
        fAmt1 float32 = 999.99
        fAmt2 float32 = 222.22
    )

    var fResult float32 = float32(int32(fAmt1*100) + int32(fAmt2*100)) / 100

    var sResult1 string = fmt.Sprintf("%.2f", fResult)

    println("Sprintf value = " + sResult1)

    var sResult2 string = strconv.FormatFloat(float64(fResult), 'f', 2, 32)

    println("FormatFloat value = " + sResult2)

}

答案1

得分: 26

fmt.Sprintfstrconv.FormatFloat在内部使用相同的字符串格式化程序,因此应该给出相同的结果。

如果要格式化的精度是可变的,那么使用FormatFloat可能更容易,因为它避免了需要构造格式字符串的需要,而Sprintf需要构造格式字符串。如果精度永远不会改变,那么你可以使用任何一个。

FormatFloat的最后一个参数控制值的四舍五入方式。根据文档:

> 它假设结果是从一个具有bitSize位的浮点值(float32为32位,float64为64位)获得的。

因此,如果你在处理与你的示例代码中一样的float32值,那么传递32是正确的。

英文:

Both fmt.Sprintf and strconv.FormatFloat use the same string formatting routine under the covers, so should give the same results.

If the precision that the number should be formatted to is variable, then it is probably easier to use FormatFloat, since it avoids the need to construct a format string as you would with Sprintf. If it never changes, then you could use either.

The last argument to FormatFloat controls how values are rounded. From the documentation:

> It rounds the
> result assuming that the original was obtained from a floating-point
> value of bitSize bits (32 for float32, 64 for float64)

So if you are working with float32 values as in your sample code, then passing 32 is correct.

答案2

得分: 4

你将在Go 1.12(2019年2月)和项目cespare/ryu中找到一个比strconv更快的替代方案:

Ryu是一个将浮点数转换为字符串的快速算法的Go实现。
它是Ulf Adams的C库的一个相当直接的Go翻译。

> strconv.FormatFloat的延迟是bimodal的,因为有一个很少使用的慢路径,成本高出数个数量级(issue 15672)。

> Ryu算法需要几个查找表。
Ulf Adams的C库实现了一个大小优化(RYU_OPTIMIZE_SIZE),它大大减小了float64表的大小,但会稍微增加一些CPU成本。

> 对于一小部分输入,Ryu给出的最后一位数与strconv不同。
这是由于strconv中的一个错误:issue 29491

Go 1.12可能会直接在strconv中包含这个新实现,但如果没有的话,你可以使用这个项目来进行更快的转换。

英文:

You will have with Go 1.12 (February 2019) and the project cespare/ryu a faster alternative to strconv:

Ryu is a Go implementation of Ryu, a fast algorithm for converting floating-point numbers to strings.
It is a fairly direct Go translation of Ulf Adams's C library.

> The strconv.FormatFloat latency is bimodal because of an infrequently-taken slow path that is orders of magnitude more expensive (issue 15672).

> The Ryu algorithm requires several lookup tables.
Ulf Adams's C library implements a size optimization (RYU_OPTIMIZE_SIZE) which greatly reduces the size of the float64 tables in exchange for a little more CPU cost.

> For a small fraction of inputs, Ryu gives a different value than strconv does for the last digit.
This is due to a bug in strconv: issue 29491.

Go 1.12 might or might not include that new implementation directly in strconv, but if it does not, you can use this project for faster conversion.

huangapple
  • 本文由 发表于 2013年9月23日 11:27:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/18951359.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定