package main
import (
"fmt"
"strconv"
)
func main() {
k := 10/3.0
i := fmt.Sprintf("%.2f", k)
f,_ := strconv.ParseFloat(i, 2)
fmt.Println(f)
}
我必须编写上面的程序,以将go float64变量的精度降低到2。 在这种情况下,我使用strconv和fmt。是否有其他逻辑方法可以完成它?
答案 0 :(得分:58)
您不需要任何额外的代码......它就像
一样简单import (
"fmt"
)
func main() {
k := 10 / 3.0
fmt.Printf("%.2f", k)
}
答案 1 :(得分:58)
我刚开始使用Go,发现令人惊讶的是它既没有“toFixed”功能(如在JavaScript中),它可以实现你想要的功能,甚至也不是“圆形”功能。
我从其他地方获取了一个单行轮函数,并且还使用了取决于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
}
用法:
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)
答案 2 :(得分:16)
我真的没有看到这一点,但你可以在没有strconv的情况下做这样的事情:
package main
import (
"fmt"
)
func main() {
untruncated := 10 / 3.0
truncated := float64(int(untruncated * 100)) / 100
fmt.Println(untruncated, truncated)
}
答案 3 :(得分:6)
没有人提到使用math/big
。与原始问题相关的结果与接受的答案相同,但如果您正在使用需要一定精度($ money $)的浮点数,那么您应该使用big.Float
。
根据原始问题:
package main
import (
"math/big"
"fmt"
)
func main() {
// original question
k := 10 / 3.0
fmt.Println(big.NewFloat(k).Text('f', 2))
}
不幸的是,你可以看到.Text
没有使用定义的舍入模式(否则这个答案可能会更有用),但似乎总是向零舍入:
j := 0.045
fmt.Println(big.NewFloat(j).SetMode(big.AwayFromZero).Text('f', 2)
// out -> 0.04
尽管如此,将浮动存储为big.Float
。
答案 4 :(得分:3)
三个人answer将我带到GitHub上的this issue,其中显示了基于math/big
的舍入值的解决方案 - 这样就可以正确使用舍入方法:
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\n", f)
}
在三个例子中也考虑了舍入模式:
j := 0.045
f := new(big.Float).SetMode(big.AwayFromZero).SetFloat64(j)
// Round to 2 digits using formatting.
f.SetPrec(8)
fmt.Printf("%.2f\n", f)
->
正确地产生了0.05
此外,Go 1.10已经发布并添加了math.Round()
功能,请参阅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
}
但是,不应使用float
来存储货币值。 (见:Why not use Double or Float to represent currency?)
解决此问题的一种方法是使用实现decimal
的库https://github.com/ericlagergren/decimal或https://github.com/shopspring/decimal
答案 5 :(得分:3)
最简单的解决方案是数字截断(假设i
是浮点型,并且您希望精度为2个小数点):
float64(int(i * 100)) / 100
例如:
i := 123456.789
x := float64(int(i * 100)) / 100
// x = 123456.78
如果您要处理大量数字(可以跨越最大值边界的数字),则应该知道上述内容可能导致serious floating point accuracy issues:
i := float64(1<<63) // 9223372036854775808.0
fmt.Println(i, float64(int64(i * 10)) / 10)
打印:9.223372036854776e+18 -9.223372036854776e+17
另请参阅:
答案 6 :(得分:1)
这是一个小小的解决方法,如何使用类型转换来循环浮动到int:
package main
import (
"fmt"
)
func main() {
k := 10 / 3.0
k = float64(int(k*100)) / 100
fmt.Println(k) // output 3.33
}
答案 7 :(得分:1)
小心经度和纬度浮动,因为截断和舍入会产生完全不同的结果......因为它可能会使你位于纬度边界的错误一侧。
答案 8 :(得分:1)
无需检查大浮点数的功能
// Rounds like 12.3416 -> 12.35
func RoundUp(val float64, precision int) float64 {
return math.Ceil(val*(math.Pow10(precision))) / math.Pow10(precision)
}
// Rounds like 12.3496 -> 12.34
func RoundDown(val float64, precision int) float64 {
return math.Floor(val*(math.Pow10(precision))) / math.Pow10(precision)
}
// Rounds to nearest like 12.3456 -> 12.35
func Round(val float64, precision int) float64 {
return math.Round(val*(math.Pow10(precision))) / math.Pow10(precision)
}
答案 9 :(得分:0)
func FloatPrecision(num float64, precision int) float64 {
p := math.Pow10(precision)
value := float64(int(num*p)) / p
return value
}
答案 10 :(得分:0)
因此,经过反复摸索,多次访问该线程,我终于找到了一个非常简单的解决方案,该解决方案使您可以非常简单地控制浮点数的精度,而无需任何怪异的数学运算!
package main
import (
"fmt"
"github.com/shopspring/decimal"
)
func main() {
k := 101.3874927181298723478
p := 5
v := decimal.NewFromFloat(k).Round(int32(p))
fmt.Println(v)
}
// 101.38749
来源:https://godoc.org/github.com/shopspring/decimal#Decimal.Round
虽然我喜欢一些简单的方法,例如"%.3f\n", k
选项,但是它们产生了一个字符串,然后我不得不使用另一个我不想做的strconv命令将其转换回浮点数。
答案 11 :(得分:-2)
从@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)
}