worksheets the nearest hundred exercises español decimals chart math go rounding

math - the - Ronda de Golang a 0.05 más cercano



rounding numbers to the nearest hundred (1)

Se ha lanzado Go 1.10 y agrega una función math.Round() . Esta función se redondea al entero más cercano (que es básicamente una operación de "redondear al 1.0 más cercano" ), y al hacerlo podemos construir una función que redondea a la unidad de nuestra elección:

func Round(x, unit float64) float64 { return math.Round(x/unit) * unit }

Probandolo

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

Pruébalo en el Go Playground .

La respuesta original sigue, que se creó antes de Go 1.10 cuando no existía math.Round() , y que también detalla la lógica detrás de nuestra función Round() . Está aquí con fines educativos.

En la era anterior a Go1.10 no había math.Round() . Pero...

Las tareas de redondeo pueden implementarse fácilmente mediante una float64 => int64 , pero se debe tener cuidado ya que la conversión a flotante a int no es redondear, sino mantener la parte entera (consulte los detalles en Ir: Convertir float64 a int con multiplicador ).

Por ejemplo:

var f float64 f = 12.3 fmt.Println(int64(f)) // 12 f = 12.6 fmt.Println(int64(f)) // 12

El resultado es 12 en ambos casos, la parte entera. Para obtener la "funcionalidad" de redondeo, simplemente añada 0.5 :

f = 12.3 fmt.Println(int64(f + 0.5)) // 12 f = 12.6 fmt.Println(int64(f + 0.5)) // 13

Hasta ahora tan bueno. Pero no queremos redondear a enteros. Si quisiéramos redondear a 1 dígito de fracción, lo multiplicaríamos por 10 antes de sumar 0.5 y convertir:

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

Así que básicamente se multiplica por el recíproco de la unidad a la que desea redondear. Para redondear a 0.05 unidades, multiplica por 1/0.05 = 20 :

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

Envolviendo esto en una función:

func Round(x, unit float64) float64 { return float64(int64(x/unit+0.5)) * unit }

Usandolo

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

Prueba los ejemplos en el Go Playground .

Tenga en cuenta que el redondeo 3.232 con la unit=0.05 no imprimirá exactamente 3.25 sino 0.35000000000000003 . Esto se debe a que los números de float64 se almacenan con precisión finita, denominada IEEE-754 . Para obtener más información, consulte la conversión de Golang float64 a int error .

También tenga en cuenta que la unit puede ser "cualquier" número. Si es 1 , entonces Round() básicamente se redondea al número entero más cercano. Si es 10 , se redondea a decenas, si es 0.01 , se redondea a 2 dígitos de fracción.

También tenga en cuenta que cuando llama a Round() con un número negativo, puede obtener un resultado sorprendente:

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

Esto se debe a que, como se dijo anteriormente, la conversión mantiene la parte entera, y por ejemplo, la parte entera de -1.6 es -1 (que es mayor que -1.6 ; mientras que la parte entera de 1.6 es 1 que es menor que 1.6 ).

Si desea que -0.363636 convierta en -0.35 lugar de -0.30 , entonces en caso de números negativos, agregue -0.5 lugar de 0.5 dentro de la función Round() . Vea nuestra función Round2() mejorada:

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 }

Y usándolo:

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

EDITAR:

Para abordar su comentario: debido a que no le "gusta" el 0.35000000000000003 no exacto, propuso formatearlo y volver a analizarlo como:

formatted, err := strconv.ParseFloat(fmt.Sprintf("%.2f", rounded), 64)

Y este "aparentemente" da como resultado el resultado exacto a medida que la impresión da exactamente 0.35 .

Pero esto es sólo una "ilusión". Dado que 0.35 no se puede representar con bits finitos utilizando el estándar IEEE-754, no importa lo que haga con el número, si lo almacena en un valor de tipo float64 , no será exactamente 0.35 (pero sí un número IEEE-754). estar muy cerca de ello). Lo que ves es fmt.Println() imprimiéndolo como 0.35 porque fmt.Println() ya hace un redondeo.

Pero si intentas imprimirlo con mayor precisión:

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))

Salida: no es mejor (podría ser aún más feo): pruébalo en Go Playground :

0.349999999999999977795539507497 3.250000000000000000000000000000 0.500000000000000000000000000000

Tenga en cuenta que, por otro lado, 3.25 y 0.5 son exactos porque pueden representarse con bits finitos exactamente, porque representan en binario:

3.25 = 3 + 0.25 = 11.01binary 0.5 = 0.1binary

Cual es la lección No vale la pena formatear y volver a analizar el resultado, ya que tampoco será exacto (solo un valor float64 diferente que, de acuerdo con las fmt.Println() formateo predeterminadas de fmt.Println() podría ser más agradable en la impresión). Si desea un buen formato impreso, simplemente formatee con precisión, como:

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 }

Y será exacto (pruébalo en Go Playground ):

0.350 3.250 0.500

O simplemente multiplíquelos por 100 y trabaje con números enteros, para que no se produzcan errores de representación o redondeo.

Estoy buscando una función para redondear al 0.05 más cercano en Golang . El resultado final de usar la función siempre debe ser un factor de 0.05.

Aquí hay algunos ejemplos de salidas para la función que estoy buscando: (La función Round no existe todavía, espero que se pueda incluir en la respuesta)

Round(0.363636) // 0.35 Round(3.232) // 3.25 Round(0.4888) // 0.5

He buscado alrededor por años y no he encontrado ninguna respuesta.