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の両方を使用していました。それを行うことができる他の論理的な方法はありますか?
私はGoを始めたばかりで、あなたが望んでいることを達成する「toFixed」機能(JavaScriptのような)がなく、「ラウンド」機能さえも持たないことに驚きました。
他の場所から1行のラウンド関数を選択し、round()に依存するtoFixed()も作成しました。
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)
私は本当にその点を見ていませんが、strconvなしでこのようなことをすることができます:
package main
import (
"fmt"
)
func main() {
untruncated := 10 / 3.0
truncated := float64(int(untruncated * 100)) / 100
fmt.Println(untruncated, truncated)
}
math/big
の使用について誰も言及していません。元の質問に関する結果は受け入れられた答えと同じですが、ある程度の精度($ money $)を必要とするfloatを使用している場合は、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
として保存することには特定の利点があります。
最も簡単な解決策は、数値の切り捨てです(i
がfloatであり、小数点以下2桁の精度が必要だと仮定します):
float64(int(i * 100)) / 100
例えば:
i := 123456.789
x := float64(int(i * 100)) / 100
// x = 123456.78
大きな数値(最大値の境界を超えることができる数値)を扱っている場合は、上記が 深刻な浮動小数点精度の問題 につながる可能性があることを知っておく必要があります。
i := float64(1<<63) // 9223372036854775808.0
fmt.Println(i, float64(int64(i * 10)) / 10)
プリント:9.223372036854776e+18 -9.223372036854776e+17
こちらもご覧ください:
answer threeveが この問題 GitHubで私にもたらしたのは、値を丸めるための_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)
}
_
Threeveの例では、丸めモードも考慮されます。
_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
を使用しないでください。 (参照: 通貨を表すためにDoubleまたはFloatを使用しない理由 )これを回避する方法の1つは、 https://github.com/のようなdecimal
を実装するライブラリを使用することですericlagergren/decimal または https://github.com/shopspring/decimal
これは、型変換を使用してfloatを前後にintに変換する方法です。
package main
import (
"fmt"
)
func main() {
k := 10 / 3.0
k = float64(int(k*100)) / 100
fmt.Println(k) // output 3.33
}
切り捨てと丸めはまったく異なる結果をもたらす可能性があるため、経度と緯度の浮動小数点数に注意してください。