Is there any standard library to convert float64 to string with fix width with maximum number of significant digits?

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

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+1e+10e+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 &gt;= 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 &gt;= 1e12 {
			// Check to see how many fraction digits fit in:
			s := fmt.Sprintf(&quot;%.g&quot;, x)
			format := fmt.Sprintf(&quot;%%12.%dg&quot;, 12-len(s))
			return fmt.Sprintf(format, x)
		}
	
		// Check to see how many fraction digits fit in:
		s := fmt.Sprintf(&quot;%.0f&quot;, x)
		if len(s) == 12 {
			return s
		}
		format := fmt.Sprintf(&quot;%%%d.%df&quot;, 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>



huangapple
  • 本文由 发表于 2016年4月9日 18:54:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/36515818.html
匿名

发表评论

匿名网友

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

确定