40

I want to display a float with the entire integer part and up to two decimals for the fractional part, without trailing zeros.

http://play.golang.org/p/mAdQl6erWX:

// Desired output: 
// "1.9"
// "10.9"
// "100.9"

fmt.Println("2g:")
fmt.Println(fmt.Sprintf("%.2g", 1.900)) // outputs "1.9"
fmt.Println(fmt.Sprintf("%.2g", 10.900)) // outputs "11"
fmt.Println(fmt.Sprintf("%.2g", 100.900)) // outputs "1e+02"

fmt.Println("\n2f:")
fmt.Println(fmt.Sprintf("%.2f", 1.900)) // outputs "1.90"
fmt.Println(fmt.Sprintf("%.2f", 10.900)) // outputs "10.90"
fmt.Println(fmt.Sprintf("%.2f", 100.900)) // outputs "100.90"

Formatting with 2g has the problem that it starts rounding when the integer increases order of magnitudes. Also, it sometimes displays numbers with an e.

Formatting with 2f has the problem that it will display trailing zeros. I could write a post-processing function that removes trailing zeros, but I rather do this with Sprintf.

Can this be done in a generic way using Sprintf?
If not, what's a good way to do this?

Blaise
  • 13,139
  • 9
  • 69
  • 97
  • In `%.Ng` N is a total number of digits, not a precision. Unfortunately I don't think you can implement your requirements using `Sprintf` only. – kostya Jul 08 '15 at 11:08

5 Answers5

82

strconv.FormatFloat(10.900, 'f', -1, 64)

This will result in 10.9.

The -1 as the third parameter tells the function to print the fewest digits necessary to accurately represent the float.

See here: https://golang.org/pkg/strconv/#FormatFloat

Eric E.
  • 836
  • 7
  • 2
7

Not sure for Sprintf but to make it worked. Just trim right, first 0 then ..

fmt.Println(strings.TrimRight(strings.TrimRight(fmt.Sprintf("%.2f", 100.900), "0"), ".")) // 100.9
fmt.Println(strings.TrimRight(strings.TrimRight(fmt.Sprintf("%.2f", 100.0), "0"), ".")) // 100
ferhatelmas
  • 3,818
  • 1
  • 21
  • 25
5

I used the below func to achive the same:

//return 45.00 with "45" or 45.50 with "45.5"
func betterFormat(num float32) string {
    s := fmt.Sprintf("%.4f", num)
    return strings.TrimRight(strings.TrimRight(s, "0"), ".")
}
Hamid Karimi
  • 615
  • 1
  • 8
  • 12
1

Use the below function to format and control the number of digits.

func FormatFloat(num float64, prc int) string {
    var (
        zero, dot = "0", "."

        str = fmt.Sprintf("%."+strconv.Itoa(prc)+"f", num)
    )
    
    return strings.TrimRight(strings.TrimRight(str, zero), dot)
}

Here is an example:

// Converts 18.24100100 to 18.24
fmt.Println(FormatFloat(18.24100100, 2))
Sadegh
  • 13
  • 5
0

We must trim those zeros ourselves. We can use TrimRight(priceStr, "0.") but I wrote more faster trimmer

func formatPrice(price float32) string {
    // truncate to 3 digits after point
    priceStr := strconv.FormatFloat(float64(price), 'f', 3, 32)
    priceStr = trimFloatTrailingZeros(priceStr)
    return priceStr
}

// trimFloatTrailingZeros the FormatFloat add padding zeros e.g. 20.900 to 20.9 or 10.0 to 10
// Note: the number must contain the decimal dot e.g. as result of format
func trimFloatTrailingZeros2(s []byte) []byte {
    i := len(s) - 1
    for ; i >= 1; i-- {
        digit := s[i]
        if digit == '0' {
        } else {
            if digit == '.' {
                return s[:i]
            } else {
                return s[:i+1]
            }
        }
    }
    return s
}
Sergey Ponomarev
  • 2,947
  • 1
  • 33
  • 43