joshlf
joshlf

Reputation: 23577

Variable floating-point precision format string

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?

Upvotes: 1

Views: 2585

Answers (3)

Denys Séguret
Denys Séguret

Reputation: 382194

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.

Upvotes: 2

Adam Smith
Adam Smith

Reputation: 54213

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)

Upvotes: 1

Sam Bartrum
Sam Bartrum

Reputation: 11

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.

Upvotes: 0

Related Questions