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 es1123
pero es impar , y1122
está más cerca que1124
) -
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;
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.