func Round(x, unit float64) float64 {
return math.Round(x/unit) * unit
}
테스트를 그것 :
fmt.Println(Round(0.363636, 0.05)) // 0.35
fmt.Println(Round(3.232, 0.05)) // 3.25
fmt.Println(Round(0.4888, 0.05)) // 0.5
fmt.Println(Round(-0.363636, 0.05)) // -0.35
fmt.Println(Round(-3.232, 0.05)) // -3.25
fmt.Println(Round(-0.4888, 0.05)) // -0.5
Go Playground에서 시도해보십시오.
원래 대답은 math.Round()
이없는 시대에 만들어졌으며 사용자 지정 Round()
기능의 논리를 자세히 설명합니다. 그것은 교육적인 목적을위한 것입니다.
이전 Go1.10 시대에는 math.Round()
이 없었습니다. 하지만 ...
반올림 작업을 쉽게 float64
=>int64
converison에 의해 구현 될 수 있지만,주의가 반올림하지만 정수 부분을 (Go: Converting float64 to int with multiplier에서 자세한 내용을 참조) 유지되지 변환을 int로 플로트로주의해야합니다. 예를 들어
:
var f float64
f = 12.3
fmt.Println(int64(f)) // 12
f = 12.6
fmt.Println(int64(f)) // 12
결과 두 경우 12
, 정수 부분이다. 반올림 '기능'을 얻으려면 0.5
을 추가하십시오.
지금까지는 그렇게 좋았습니다. 그러나 우리는 정수로 반올림하고 싶지 않습니다. 우리는 1 개 분수 자리에 모아 원했다면, 우리는 0.5
를 추가하고 변환하기 전에 10을 곱합니다 :
f = 12.31
fmt.Println(float64(int64(f*10+0.5))/10) // 12.3
f = 12.66
fmt.Println(float64(int64(f*10+0.5))/10) // 12.7
을 그래서 기본적으로 당신은 당신이 라운드 할 장치의 역수로 곱하면됩니다.1/0.05 = 20
에 의해 곱셈, 0.05
단위로 반올림하려면
f = 12.31
fmt.Println(float64(int64(f*20+0.5))/20) // 12.3
f = 12.66
fmt.Println(float64(int64(f*20+0.5))/20) // 12.65
함수로이 포장 :
func Round(x, unit float64) float64 {
return float64(int64(x/unit+0.5)) * unit
}
그것을 사용 :
fmt.Println(Round(0.363636, 0.05)) // 0.35
fmt.Println(Round(3.232, 0.05)) // 3.25
fmt.Println(Round(0.4888, 0.05)) // 0.5
가 Go Playground의 예를보십시오.
unit=0.05
으로 반올림하면 3.25
이 아니라 0.35000000000000003
으로 정확하게 인쇄됩니다. float64
숫자는 IEEE-754 표준이라는 유한 정밀도를 사용하여 저장되기 때문입니다. 자세한 내용은 Golang converting float64 to int error을 참조하십시오.
또한 unit
은 "모든"숫자 일 수 있습니다. 1
인 경우 Round()
은 기본적으로 가장 가까운 정수로 반올림됩니다. 10
인 경우 십진수로 반올림되며 0.01
인 경우 2 소수 자릿수로 반올림됩니다.
또한 음수로 Round()
를 호출 할 때, 당신은 놀라운 결과를 얻을 수 있습니다 :
fmt.Println(Round(-0.363636, 0.05)) // -0.3
fmt.Println(Round(-3.232, 0.05)) // -3.2
fmt.Println(Round(-0.4888, 0.05)) // -0.45
이 -as가하는 이전에 변환 정수 부분을 유지, 그리고 예를 들어, 정수 부분에 대해 상기 있기 때문이다 -1.6
은 보다 크고 1.6
의 정수 부분은 1.6
보다 작은 1
인 반면 -1
입니다.
당신이 -0.35
대신 -0.30
가 될 -0.363636
을 원한다면, 음수의 경우에는 Round()
함수 내에서 -0.5
대신 0.5
추가 할 수 있습니다.
func Round2(x, unit float64) float64 {
if x > 0 {
return float64(int64(x/unit+0.5)) * unit
}
return float64(int64(x/unit-0.5)) * unit
}
그리고 그것을 사용 : 우리의 개선 Round2()
함수를 참조
fmt.Println(Round2(-0.363636, 0.05)) // -0.35
fmt.Println(Round2(-3.232, 0.05)) // -3.25
fmt.Println(Round2(-0.4888, 0.05)) // -0.5
편집 :
당신의 코멘트를 해결하기 위해 : 당신은 비 "처럼"하지 않기 때문에 -exact 0.35000000000000003
, 형식을 지정하고 다시 구문 분석을 제안했습니다.
formatted, err := strconv.ParseFloat(fmt.Sprintf("%.2f", rounded), 64)
그리고이 "겉보기"결과는 정확히 인쇄 결과로 0.35
이됩니다.
그러나 이것은 단지 "환상"입니다. 0.35
은 IEEE-754 표준을 사용하여 유한 비트로 표시 할 수 없으므로 숫자로 어떤 작업을하든 관계없이 float64
유형의 값으로 저장하면 정확히 0.35
(IEEE-754 번호 매우 가까이에있다). fmt.Println()
은 이미 에 약간의 반올림을하기 때문에 0.35
으로 표시됩니다.(심지어 이보다 수 있습니다) 그렇지 좋네요 :
fmt.Printf("%.30f\n", Round(0.363636, 0.05))
fmt.Printf("%.30f\n", Round(3.232, 0.05))
fmt.Printf("%.30f\n", Round(0.4888, 0.05))
출력은 : 당신이 더 높은 정밀도로 인쇄하려고하면
그러나 Go Playground에 그것을 시도 :
0.349999999999999977795539507497
3.250000000000000000000000000000
0.500000000000000000000000000000
참고가에 다른 하나는 3.25
과 0.5
이 정확하기 때문에 이진수로 표현하기 때문에 정확하게 유한 비트로 나타낼 수 있습니다.
3.25 = 3 + 0.25 = 11.01binary
0.5 = 0.1binary
수업이란 무엇입니까? 결과를 서식 지정하고 다시 구문 분석 할 필요가 없습니다. 정확한 값이 아니기 때문에 (인쇄시 기본 fmt.Println()
서식 규칙에 따라 float64
값이 다를 수 있습니다). 당신이 좋은 인쇄 형식을 원하는 경우처럼 정밀하게 포맷 :
func main() {
fmt.Printf("%.3f\n", Round(0.363636, 0.05))
fmt.Printf("%.3f\n", Round(3.232, 0.05))
fmt.Printf("%.3f\n", Round(0.4888, 0.05))
}
func Round(x, unit float64) float64 {
return float64(int64(x/unit+0.5)) * unit
}
그리고합니다 (Go Playground에 그것을 시도) 정확합니다
0.350
3.250
0.500
을하거나 100
곱해 및 작업 정수형이므로 표현이나 반올림 오류가 발생할 수 없습니다.
온라인으로 하나를 찾았지만 질문에 답을 얻지 못했습니다./ – Acidic
Related : [Go : 승수로 정수로 float64 변환하기] (http://stackoverflow.com/questions/33206059/) go-converting-float64-int-with-multiplier) – icza
올바른 결과를 제공하는 반올림 함수가있는 경우이를 잘라내어 결과의 정밀도를 관리하면됩니다. 일종의 ham-fisted 접근 방식은 https://play.golang.org/p/DRTTkQQI42 일 것이다. (가장자리 테스트는 안됨) – abhink