英文:
Is there any standard library to convert float64 to string with fix width with maximum number of significant digits?
问题
在打印一个固定宽度为12的表格时,我们需要打印float64
类型的数字:
fmt.Printf("%12.6g\n", 9.405090880450127e+119) //"9.40509e+119"
fmt.Printf("%12.6g\n", 0.1234567890123) // " 0.123457"
fmt.Printf("%12.6g\n", 123456789012.0) // " 1.23457e+11"
我们更喜欢使用0.1234567890而不是" 0.123457",因为我们会丢失6个有效数字。
我们更喜欢使用123456789012而不是" 1.23457e+11",因为我们会丢失6个有效数字。
是否有任何标准库可以将float64
转换为具有固定宽度和最大有效数字数量的字符串?
提前感谢。
英文:
Imagine for printing in a 12 fixed width table we need printing float64
numbers:
fmt.Printf("%12.6g\n", 9.405090880450127e+119) //"9.40509e+119"
fmt.Printf("%12.6g\n", 0.1234567890123) //" 0.123457"
fmt.Printf("%12.6g\n", 123456789012.0) //" 1.23457e+11"
We prefer 0.1234567890 to " 0.123457" we lose 6 significant digits.
We prefer 123456789012 to " 1.23457e+11" we lose 6 significant digits.
Is there any standard library to convert float64
to string
with fix width with maximum number of significant digits?
Thanks in Advance.
答案1
得分: 2
基本上,你有两种输出格式:科学计数法和常规形式。这两种格式之间的转折点是 1e12
。
所以你可以分支判断 x >= 1e12
。在两个分支中,你可以使用 0 个小数位进行格式化,以查看数字的长度,从而计算出多少个小数位适合于 12 位宽度,然后构造最终的格式字符串,使用计算出的精度。
在科学计数法中也需要进行预检查(%g
),因为指数的宽度可能会变化(例如 e+1
、e+10
、e+100
)。
这是一个示例实现。这只是为了让你开始,但并不意味着处理所有情况,也不是最高效的解决方案(但相对简单且能完成工作):
// format12 将 x 格式化为 12 个字符长。
func format12(x float64) string {
if x >= 1e12 {
// 检查有多少个小数位适合:
s := fmt.Sprintf("%.g", x)
format := fmt.Sprintf("%%12.%dg", 12-len(s))
return fmt.Sprintf(format, x)
}
// 检查有多少个小数位适合:
s := fmt.Sprintf("%.0f", x)
if len(s) == 12 {
return s
}
format := fmt.Sprintf("%%%d.%df", len(s), 12-len(s)-1)
return fmt.Sprintf(format, x)
}
测试它:
fs := []float64{0, 1234.567890123, 0.1234567890123, 123456789012.0, 1234567890123.0,
9.405090880450127e+9, 9.405090880450127e+19, 9.405090880450127e+119}
for _, f := range fs {
fmt.Println(format12(f))
}
输出(在 [Go Playground][1] 上尝试):
0.0000000000
0.1234567890
1234.5678901
123456789012
1.234568e+12
9405090880.5
9.405091e+19
9.40509e+119
[1]: http://play.golang.org/p/_xLlpxs-WF
<details>
<summary>英文:</summary>
Basically you have 2 output formats: either a scientific notation or a regular form. The turning point between those 2 formats is `1e12`.
So you can branch if `x >= 1e12`. In both branches you may do a formatting with 0 fraction digits to see how long the number will be, so you can calculate how many fraction digits will fit in for 12 width, and so you can construct the final format string, using the calculated precision.
The pre-check is required in the scientific notation too (`%g`), because the width of exponent may vary (e.g. `e+1`, `e+10`, `e+100`).
Here is an example implementation. This is to get you started, but it does not mean to handle all cases, and it is not the most efficient solution (but relatively simple and does the job):
// format12 formats x to be 12 chars long.
func format12(x float64) string {
if x >= 1e12 {
// Check to see how many fraction digits fit in:
s := fmt.Sprintf("%.g", x)
format := fmt.Sprintf("%%12.%dg", 12-len(s))
return fmt.Sprintf(format, x)
}
// Check to see how many fraction digits fit in:
s := fmt.Sprintf("%.0f", x)
if len(s) == 12 {
return s
}
format := fmt.Sprintf("%%%d.%df", len(s), 12-len(s)-1)
return fmt.Sprintf(format, x)
}
Testing it:
fs := []float64{0, 1234.567890123, 0.1234567890123, 123456789012.0, 1234567890123.0,
9.405090880450127e+9, 9.405090880450127e+19, 9.405090880450127e+119}
for _, f := range fs {
fmt.Println(format12(f))
}
Output (try it on the [Go Playground][1]):
0.0000000000
0.1234567890
1234.5678901
123456789012
1.234568e+12
9405090880.5
9.405091e+19
9.40509e+119
[1]: http://play.golang.org/p/_xLlpxs-WF
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论