package main
import (
"fmt"
"strconv"
)
func main() {
k := 10/3.0
i := fmt.Sprintf("%.2f", k)
f,_ := strconv.ParseFloat(i, 2)
fmt.Println(f)
}
I had to write the program above to decrease the precision of a go float64 variable to 2. In this case I was using both strconv and fmt. Is there some other logical method by which it can be done ?
You don't need any extra code ... its as simple as
import (
"fmt"
)
func main() {
k := 10 / 3.0
fmt.Printf("%.2f", k)
}
I really don't see the point, but you could do something like this without strconv:
package main
import (
"fmt"
)
func main() {
untruncated := 10 / 3.0
truncated := float64(int(untruncated * 100)) / 100
fmt.Println(untruncated, truncated)
}
modify from @creack
package main
import (
"fmt"
)
func main() {
//untruncated := 10/3.0
untruncated := 4.565
tmp := int(untruncated*100)
last := int(untruncated*1000)-tmp*10
if last>=5{
tmp += 1
}
truncated := float64(tmp)/100
fmt.Println(untruncated, truncated)
}
I'm just starting in Go and found it surprising that it has neither a "toFixed" function (as in JavaScript), which would accomplish what you want, nor even a "round" function.
I picked up a one-liner round function from elsewhere, and also made toFixed() which depends on round():
func round(num float64) int {
return int(num + math.Copysign(0.5, num))
}
func toFixed(num float64, precision int) float64 {
output := math.Pow(10, float64(precision))
return float64(round(num * output)) / output
}
Usage:
fmt.Println(toFixed(1.2345678, 0)) // 1
fmt.Println(toFixed(1.2345678, 1)) // 1.2
fmt.Println(toFixed(1.2345678, 2)) // 1.23
fmt.Println(toFixed(1.2345678, 3)) // 1.235 (rounded up)
No one has mentioned using math/big
. The results as pertains to the original question are the same as the accepted answer, but if you are working with floats that require a degree of precision ($money$), then you should use big.Float
.
Per the original question:
package main
import (
"math/big"
"fmt"
)
func main() {
// original question
k := 10 / 3.0
fmt.Println(big.NewFloat(k).Text('f', 2))
}
Unfortunately, you can see that .Text
does not use the defined rounding mode (otherwise this answer might be more useful), but rather always seems to round toward zero:
j := 0.045
fmt.Println(big.NewFloat(j).SetMode(big.AwayFromZero).Text('f', 2)
// out -> 0.04
Nevertheless, there are certain advantages to having your float stored as a big.Float
.
This is a little workaround how can you round float using type conversion to int back and forth:
package main
import (
"fmt"
)
func main() {
k := 10 / 3.0
k = float64(int(k*100)) / 100
fmt.Println(k) // output 3.33
}
The answer by threeve brought me to this issue on GitHub where a solution based on math/big
for rounding values is presented - this way the rounding method is used correctly:
package main
import (
"fmt"
"math/big"
)
func main() {
f := new(big.Float).SetMode(big.ToNearestEven).SetFloat64(10/3.0)
// Round to 2 digits using formatting.
f.SetPrec(8)
fmt.Printf("%.2f
", f)
}
The rounding mode is also respected in threeve's example:
j := 0.045
f := new(big.Float).SetMode(big.AwayFromZero).SetFloat64(j)
// Round to 2 digits using formatting.
f.SetPrec(8)
fmt.Printf("%.2f
", f)
->
correctly yields 0.05
Also, Go 1.10 has been released and added a math.Round()
function, see this excellent answer by icza: Golang Round to Nearest 0.05
package main
import (
"fmt"
"math"
)
func main() {
fmt.Println(Round(10/3.0, 0.01))
}
func Round(x, unit float64) float64 {
return math.Round(x/unit) * unit
}
However, one should not use float
for storing monetary values. (See: Why not use Double or Float to represent currency?) One way around this is using a library that implements decimal
like https://github.com/ericlagergren/decimal or https://github.com/shopspring/decimal
Be careful with longitude and latitude float as truncating and rounding can yield completely different results... as it can put you on the wrong side of a latitude boundary.
The simplest solution is numeric truncation (assuming i
is a float and you want a precision of 2 decimal points):
float64(int(i * 100)) / 100
For example:
i := 123456.789
x := float64(int(i * 100)) / 100
// x = 123456.78
If you're dealing with large numbers (numbers that can cross the max value boundaries), you should know that the above can lead to serious floating point accuracy issues:
i := float64(1<<63) // 9223372036854775808.0
fmt.Println(i, float64(int64(i * 10)) / 10)
Prints: 9.223372036854776e+18 -9.223372036854776e+17
See also: