英文:
Variable floating-point precision format string
问题
我正在尝试将浮点数以百分比形式打印出来,并且希望小数点后的位数根据需要进行变化。目前我有以下代码:
fmt.Printf("%.2f%%\n", 100*(value/total))
问题是,如果我的百分比恰好是50,我将得到以下输出:
50.00%
而我想要的是:
50%
有没有办法让格式字符串指示只在需要时使用最多2位小数精度?
英文:
I'm trying to print floating point numbers as percentages, and I'd like for the number of digits after the decimal place to vary as needed. Currently I have:
fmt.Printf("%.2f%%\n", 100*(value/total))
The problem is that if my percentage is, say, exactly 50, I will get the following output:
50.00%
While what I want is to get:
50%
Is there any way for the format string to indicate that a maximum of 2 digits of precision should be used, but only if needed?
答案1
得分: 2
在fmt
包中没有直接的解决方案。
但是你可以使用正则表达式来去除末尾的小数点和零:
r, _ := regexp.Compile(`\.?0*$`)
fmt.Printf("%s%%\n", r.ReplaceAllString(fmt.Sprintf("%.2f", 100*(value/total)),""))
额外提示:相同的正则表达式也适用于任意数量的尾随零。
顺便提一下:你将以相同的方式显示50.0041
和50
,这可能会有点误导。
英文:
There's no direct solution with the fmt
package.
But you can remove the dot and zeros at end with a regular expression:
r, _ := regexp.Compile(`\.?0*$`)
fmt.Printf("%s%%\n", r.ReplaceAllString(fmt.Sprintf("%.2f", 100*(value/total)),""))
Bonus: the same regex works for any number of trailing zeros.
Side note: You'll display 50.0041
the same way than 50
, which might be a little misleading.
答案2
得分: 1
在fmt
中没有办法通过其他标志或方法来实现这一点。你需要自己编写逻辑。你可以这样做:
var final string
doubledecimal := fmt.Sprintf("%.2f", 100*value/total)
if doubledecimal[len(doubledecimal)-2:] == "00" {
final = doubledecimal[:len(doubledecimal)-3]
} else {
final = doubledecimal
}
fmt.Printf("%s%%\n", final)
你也可以使用strings.Split
来分割小数点并进行处理。
你甚至可以将50.10%
转换为50.1%
。
doubledecimal := fmt.Sprintf("%.2f", 100*value/total)
// 去除尾部的零
for doubledecimal[len(doubledecimal)-1] == '0' {
doubledecimal = doubledecimal[:len(doubledecimal)-1]
}
// 如果小数点在尾部,则去除小数点
if doubledecimal[len(doubledecimal)-1] == '.' {
doubledecimal = doubledecimal[:len(doubledecimal)-1]
}
fmt.Printf("%s%%\n", doubledecimal)
英文:
There's no way to do that inside fmt
with e.g. another flag or what have you. You'll have to write out the logic yourself. You could do something like:
var final string
doubledecimal := fmt.Sprintf("%.2f", 100*value/total)
if doubledecimal[len(doubledecimal)-2:] == "00" {
final = doubledecimal[:len(doubledecimal)-3]
} else {
final = doubledecimal
}
fmt.Printf("%s%%\n, final)
You could similarly use strings.Split
to split on the decimal point and work from there.
You could even adjust this to turn 50.10%
into 50.1%
.
doubledecimal := fmt.Sprintf("%.2f", 100*value/total)
// Strip trailing zeroes
for doubledecimal[len(doubledecimal)-1] == 0 {
doubledecimal = doubledecimal[:len(doubledecimal)-1]
}
// Strip the decimal point if it's trailing.
if doubledecimal[len(doubledecimal)-1] == "." {
doubledecimal = doubledecimal[:len(doubledecimal)-1]
}
fmt.Printf("%s%%\n", doubledecimal)
答案3
得分: 0
一种方法是使用if语句来控制打印输出,即如果结果可以整除1(result%1 == 0),则打印结果时不显示小数位。否则,按照你上面所做的方式打印到小数点后两位。不确定是否有更简洁的方法,但我认为这应该可以工作。
英文:
One way could be to have an if statement controlling the print output, i.e. if the result is cleanly divisible by 1 (result%1 == 0) then print the result to no decimal places. Otherwise print to .2f as you've done above. Not sure if there is a shorter way of doing this, but I think this should work.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论