visual solo redondear quitar poner mostrar hacia entero decimales arriba c# algorithm math rounding

c# - solo - ¿Cómo redondear al entero par más cercano?



redondear en visual basic (4)

Mi último objetivo siempre es redondear al entero par más cercano .

Por ejemplo, el número 1122.5196 que quiero como resultado 1122 . He probado estas opciones:

Math.Round(1122.5196d, 0, MidpointRounding.ToEven); // result 1123 Math.Round(1122.5196d, 0, MidpointRounding.AwayFromZero); // result 1123

Al final, lo que me gustaría obtener es siempre el intenger más cercano . Por ejemplo:

  • 1122.51 --> 1122
  • 1122.9 --> 1122 (porque el int más cercano es 1123 pero es impar , y 1122 está más cerca que 1124 )
  • 1123.0 --> 1124 (el siguiente valor par , el siguiente valor par más alto )

Solo trabajo con números positivos .

Y así.

¿Hay algún método que haga eso o debo implementar mi propio método?


Aquí hay un ejemplo de la función que encontré en msdn, que solo producirá los números más cercanos que se ajusten bien a su caso,

using System; class Example { public static void Main() { // Define a set of Decimal values. decimal[] values = { 1.45m, 1.55m, 123.456789m, 123.456789m, 123.456789m, -123.456m, new Decimal(1230000000, 0, 0, true, 7 ), new Decimal(1230000000, 0, 0, true, 7 ), -9999999999.9999999999m, -9999999999.9999999999m }; // Define a set of integers to for decimals argument. int[] decimals = { 1, 1, 4, 6, 8, 0, 3, 11, 9, 10}; Console.WriteLine("{0,26}{1,8}{2,26}", "Argument", "Digits", "Result" ); Console.WriteLine("{0,26}{1,8}{2,26}", "--------", "------", "------" ); for (int ctr = 0; ctr < values.Length; ctr++) Console.WriteLine("{0,26}{1,8}{2,26}", values[ctr], decimals[ctr], Decimal.Round(values[ctr], decimals[ctr])); } } // The example displays the following output: // Argument Digits Result // -------- ------ ------ // 1.45 1 1.4 // 1.55 1 1.6 // 123.456789 4 123.4568 // 123.456789 6 123.456789 // 123.456789 8 123.456789 // -123.456 0 -123 // -123.0000000 3 -123.000 // -123.0000000 11 -123.0000000 // -9999999999.9999999999 9 -10000000000.000000000 // -9999999999.9999999999 10 -9999999999.9999999999

"Al redondear los valores del punto medio, el algoritmo de redondeo realiza una prueba de igualdad. Debido a problemas de representación y precisión binaria en el formato de punto flotante, el valor devuelto por el método puede ser inesperado".


Intente esto (usemos Math.Round con MidpointRounding.AwayFromZero para obtener "el siguiente valor par" pero escalado - factor 2 ):

double source = 1123.0; // 1124.0 double result = Math.Round(source / 2, MidpointRounding.AwayFromZero) * 2;

Manifestación:

double[] tests = new double[] { 1.0, 1123.1, 1123.0, 1122.9, 1122.1, 1122.0, 1121.5, 1121.0, }; string report = string.Join(Environment.NewLine, tests .Select(item => $"{item,6:F1} -> {Math.Round(item / 2, MidpointRounding.AwayFromZero) * 2}")); Console.Write(report);

Salir:

1.0 -> 2 // In case of tie, next even value 1123.1 -> 1124 1123.0 -> 1124 // In case of tie, next even value 1122.9 -> 1122 1122.1 -> 1122 1122.0 -> 1122 1121.5 -> 1122 1121.0 -> 1122 // In case of tie, next even value


La razón por la que está obteniendo el resultado 1123 incluso al usar

Math.Round(1122.5196d, 0, MidpointRounding.ToEven);

es porque eso es exactamente lo que le has pedido al compilador que haga. Cuando redondee a par con decimales, asegúrese de recordar que 1123.0 es par.

es decir. 1122.51 redondeado a par se convierte en 1123.0 (tenga en cuenta que como es decimal, siempre mantendrá su posición decimal y, por lo tanto, el .0 hace que este sea un número par).

En su lugar, escribiría una función para hacer esto, algo como:

private int round_up_to_even(double number_to_round) { int converted_to_int = Convert.ToInt32(number_to_round); if (converted_to_int %2 == 0) { return converted_to_int; } double difference = (converted_to_int + 1) - number_to_round; if (difference <= 0.5) { return converted_to_int + 1; } return converted_to_int - 1; }


Un trazador de líneas:

double RoundToNearestEven(double value) => Math.Truncate(value) + Math.Truncate(value) % 2;

Fiddle

Explicación: si tenemos un número par con algunos dígitos después del punto flotante, necesitamos simplemente deshacernos de esos dígitos. Si tenemos un número impar, debemos hacer lo mismo y luego pasar al siguiente entero que se garantiza que sea par.

PD Gracias a @DmitryBychenko por señalar que lanzar un doble o mucho tiempo no es la mejor idea.