C ++: redondeando al múltiplo más cercano de un número


168

OK, estoy casi avergonzado de publicar esto aquí (y lo eliminaré si alguien vota para cerrar) ya que parece una pregunta básica.

¿Es esta la forma correcta de redondear a un múltiplo de un número en C ++?

Sé que hay otras preguntas relacionadas con esto, pero estoy especialmente interesado en saber cuál es la mejor manera de hacer esto en C ++:

int roundUp(int numToRound, int multiple)
{
 if(multiple == 0)
 {
  return numToRound;
 }

 int roundDown = ( (int) (numToRound) / multiple) * multiple;
 int roundUp = roundDown + multiple; 
 int roundCalc = roundUp;
 return (roundCalc);
}

Actualización: lo siento, probablemente no he dejado en claro la intención. Aquí hay unos ejemplos:

roundUp(7, 100)
//return 100

roundUp(117, 100)
//return 200

roundUp(477, 100)
//return 500

roundUp(1077, 100)
//return 1100

roundUp(52, 20)
//return 60

roundUp(74, 30)
//return 90

3
Tiene un error en su lógica. Digamos que quiero redondear 4 al múltiplo más cercano de 2. roundDown = (4/2) * 2 = 4; redondeo = 4 + 2; entonces roundCalc = 6. Supongo que querría devolver 4 en ese caso.
Niki Yoshiuchi el

Esto no funciona para el redondeo (30,30). Se da 60 como respuesta, que aún debe dar 30 como respuesta ..
bsobaid

@bsobaid: Mira mi respuesta en la parte inferior. Es un poco más simple que otras soluciones aquí, aunque esas también deberían funcionar
Niklas B.

3
Sus casos de prueba son ejemplos que faltan notoriamente que involucran números negativos, casos donde la división es exacta, casos donde la división es casi exacta y casos donde los números están muy cerca de los límites del rango de int.

1
Robben_Ford_Fan_boy, la edición con la respuesta que buscabas debería eliminarse. Si difiere de las respuestas dadas, puede publicar su propia respuesta. Tal como están las cosas, esa respuesta tiene problemas que deberían abordarse en la sección de respuestas.
chux - Restablece a Mónica el

Respuestas:


161

Esto funciona para números positivos, no estoy seguro sobre negativos. Solo usa matemática entera.

int roundUp(int numToRound, int multiple)
{
    if (multiple == 0)
        return numToRound;

    int remainder = numToRound % multiple;
    if (remainder == 0)
        return numToRound;

    return numToRound + multiple - remainder;
}

Editar: Aquí hay una versión que funciona con números negativos, si por "arriba" quieres decir un resultado que siempre es> = la entrada.

int roundUp(int numToRound, int multiple)
{
    if (multiple == 0)
        return numToRound;

    int remainder = abs(numToRound) % multiple;
    if (remainder == 0)
        return numToRound;

    if (numToRound < 0)
        return -(abs(numToRound) - remainder);
    else
        return numToRound + multiple - remainder;
}

+1 En mi opinión, definitivamente la solución más agradable y legible.
Robben_Ford_Fan_boy

1
Agregue if(number<0){ multiple = multiple*(-1); }al comienzo para redondear los números negativos en la dirección correcta
Josh

44
@ Josh: ¿Por qué usar la multiplicación? if(number<0) multiple = -multiplees mas facil.
md5

Esto no funciona para el redondeo (30,30). Da 60 como respuesta, aún debe dar 30 como respuesta.
bsobaid

@bsobaid imposible. La if (remainder == 0)prueba debe ocuparse de ese caso. Funciona para mí: ideone.com/Waol7B
Mark Ransom

114

Sin condiciones:

int roundUp(int numToRound, int multiple) 
{
    assert(multiple);
    return ((numToRound + multiple - 1) / multiple) * multiple;
}

Esto funciona como redondear desde cero para números negativos

EDITAR: versión que funciona también para números negativos

int roundUp(int numToRound, int multiple) 
{
    assert(multiple);
    int isPositive = (int)(numToRound >= 0);
    return ((numToRound + isPositive * (multiple - 1)) / multiple) * multiple;
}

Pruebas


Si multiplees una potencia de 2 (más rápido en ~ 3.7 veces http://quick-bench.com/sgPEZV9AUDqtx2uujRSa3-eTE80 )

int roundUp(int numToRound, int multiple) 
{
    assert(multiple && ((multiple & (multiple - 1)) == 0));
    return (numToRound + multiple - 1) & -multiple;
}

Pruebas


24
+1 para el poder de la versión 2. Muy útil ya que evita totalmente el costo de multiplicaciones, divisiones o módulos.
Nikos C.

¿Estás seguro de que estos algoritmos no tienen condiciones previas? ¿Qué pasa con los números negativos? El comportamiento parece estar indefinido en pre-C ++ 11 .
cubuspl42

> ¿Qué pasa con los números negativos? Como se describe, esto funciona para números negativos como redondear desde cero.
KindDragon

Leí "redondeando hacia arriba" como redondeando hacia el infinito positivo, no redondeando desde cero.

8
Tenga en cuenta que & ~(x - 1)es lo mismo que & -xpara la aritmética del complemento a dos.
Todd Lehman

39

Esto funciona cuando el factor siempre será positivo:

int round_up(int num, int factor)
{
    return num + factor - 1 - (num - 1) % factor;
}

Editar: esto vuelve round_up(0,100)=100. Consulte el comentario de Paul a continuación para obtener una solución que regrese round_up(0,100)=0.


1
Parece ser el caso más corto que maneja el caso 'ya-un-múltiple'.
harningt

1
La mejor solución en términos de número de operaciones costosas. Solo usa una sola división y no multiplicación
Niklas B.

3
round_up (0, 100) == 100 en lugar de 0 como en la respuesta aceptada
Gregory

77
¿No debería ser num + factor - 1 - (num + factor - 1) % factor?
Paul

66
num - 1 - (num - 1) % factor + factorrealiza el mismo cálculo sin el riesgo de desbordamiento de enteros.

24

Esta es una generalización del problema de "¿cómo puedo saber cuántos bytes tomarán n bits? (A: (n bits + 7) / 8).

int RoundUp(int n, int roundTo)
{
    // fails on negative?  What does that mean?
    if (roundTo == 0) return 0;
    return ((n + roundTo - 1) / roundTo) * roundTo; // edit - fixed error
}

1
Esto no se redondea al siguiente múltiplo de un número.
aaaa bbbb

77
Me gusta esta solución porque si roundTo será una potencia de 2, puede eliminar el / y * y terminar con nada más que operaciones baratas (x = roundTo - 1; return (n + x) & ~ x;)
Trejkaz

@Trejkaz no. Debería ser (x = roundTo - 1; return (n+x)&~roundTo;)como en mi respuesta
KindDragon

@KindDragon que produce el resultado incorrecto para mí, pero si lo corrijo para decir ~ x en lugar de ~ roundTo, obtengo el resultado esperado. En Java 8 de todos modos.
Trejkaz

@KindDragon: la máscara AND debe ser 0xFFF...000, no 0xFFF7FFFo algo, por lo que desea la negación del complemento de 2 ( -: menos) con una potencia de 2, o un cambio de bits en uno menos que una potencia de 2 (el complemento de uno inverso, ~tilde no menos). Entonces (n+x) & ~xo (n-roundTo+1) & -roundTo.
Peter Cordes

14
int roundUp(int numToRound, int multiple)
{
 if(multiple == 0)
 {
  return 0;
 }
 return ((numToRound - 1) / multiple + 1) * multiple;  
}

Y no hay necesidad de perder el tiempo con las condiciones


11

Para cualquiera que busque una respuesta breve y dulce. Esto es lo que usé. No contabilizar los negativos.

n - (n % r)

Eso devolverá el factor anterior.

(n + r) - (n % r)

Volveremos la próxima. Espero que esto ayude a alguien. :)


9
float roundUp(float number, float fixedBase) {
    if (fixedBase != 0 && number != 0) {
        float sign = number > 0 ? 1 : -1;
        number *= sign;
        number /= fixedBase;
        int fixedPoint = (int) ceil(number);
        number = fixedPoint * fixedBase;
        number *= sign;
    }
    return number;
}

Esto funciona para cualquier número flotante o base (por ejemplo, puede redondear -4 al 6,75 más cercano). En esencia, se está convirtiendo en un punto fijo, redondeando allí y luego volviendo a convertir. Maneja los negativos redondeando LEJOS desde 0. También maneja un redondeo negativo al valor, esencialmente convirtiendo la función en roundDown.

Una versión específica de int se parece a:

int roundUp(int number, int fixedBase) {
    if (fixedBase != 0 && number != 0) {
        int sign = number > 0 ? 1 : -1;
        int baseSign = fixedBase > 0 ? 1 : 0;
        number *= sign;
        int fixedPoint = (number + baseSign * (fixedBase - 1)) / fixedBase;
        number = fixedPoint * fixedBase;
        number *= sign;
    }
    return number;
}

Cuál es más o menos la respuesta del zócalo, con el soporte de entrada negativa agregado.


He probado el código float roundUp con double, me funciona. Realmente resuelve mi problema.
Ashif

1
¿Qué pasa double round(double value, double multiple) { double sign = value; multiple = std::copysign(multiple, 1.0); value = std::copysign(value, 1.0); return std::copysign(multiple * std::ceil(value / multiple), sign); }o cambiar el techo por redondeo para obtener redondeo?
Troyseph

8

Este es el enfoque moderno de c ++ que utiliza una función de plantilla que funciona para float, double, long, int y short (pero no para long long y long double debido a los valores dobles utilizados).

#include <cmath>
#include <iostream>

template<typename T>
T roundMultiple( T value, T multiple )
{
    if (multiple == 0) return value;
    return static_cast<T>(std::round(static_cast<double>(value)/static_cast<double>(multiple))*static_cast<double>(multiple));
}

int main()
{
    std::cout << roundMultiple(39298.0, 100.0) << std::endl;
    std::cout << roundMultiple(20930.0f, 1000.0f) << std::endl;
    std::cout << roundMultiple(287399, 10) << std::endl;
}

Pero puede agregar fácilmente soporte para long longy long doublecon la especialización de plantilla como se muestra a continuación:

template<>
long double roundMultiple<long double>( long double value, long double multiple)
{
    if (multiple == 0.0l) return value;
    return std::round(value/multiple)*multiple;
}

template<>
long long roundMultiple<long long>( long long value, long long multiple)
{
    if (multiple == 0.0l) return value;
    return static_cast<long long>(std::round(static_cast<long double>(value)/static_cast<long double>(multiple))*static_cast<long double>(multiple));
}

Para crear funciones para redondear, use std::ceily para redondear siempre hacia abajo std::floor. Mi ejemplo de arriba es redondear usando std::round.

Cree la función de plantilla "redondear hacia arriba" o mejor conocida como "techo redondo" como se muestra a continuación:

template<typename T>
T roundCeilMultiple( T value, T multiple )
{
    if (multiple == 0) return value;
    return static_cast<T>(std::ceil(static_cast<double>(value)/static_cast<double>(multiple))*static_cast<double>(multiple));
}

Cree la función de plantilla "redondear hacia abajo" o mejor conocida como "piso redondo" como se muestra a continuación:

template<typename T>
T roundFloorMultiple( T value, T multiple )
{
    if (multiple == 0) return value;
    return static_cast<T>(std::floor(static_cast<double>(value)/static_cast<double>(multiple))*static_cast<double>(multiple));
}

1
más 1, aunque algunas personas pueden encontrar más razonable devolver 0 cuando mulitple == 0
stijn

3
Tenga cuidado, porque la conversión de int64_t a double puede ser con pérdida, por lo que no es tan genérico como puede parecer.
Adrian McCarthy

@AdrianMcCarthy Sí, debe crear las especializaciones de plantilla correctas como se muestra arriba. Como puede ver, implemento dos funciones adicionales para long longy long double. Obviamente, lo mismo debe hacerse para las otras dos funciones.
Flovdis

Creo que este es, con mucho, el más lento de todos, pero no debería ser así. Todo lo que necesita hacer es std :: enable_if_t y hacer dos ramas para enteros y flotantes. También podría hacer un mejor uso de los numeric_limits y ver si la mantisa es lo suficientemente grande como para ajustarse realmente al valor. Eso agregaría seguridad.
los cerdos

5

En primer lugar, su condición de error (múltiple == 0) probablemente debería tener un valor de retorno. ¿Qué? No lo sé. Tal vez quieras lanzar una excepción, eso depende de ti. Pero, no devolver nada es peligroso.

En segundo lugar, debe verificar que numToRound ya no sea un múltiplo. De lo contrario, cuando agregue multiplea roundDown, obtendrá la respuesta incorrecta.

En tercer lugar, tus yesos están equivocados. Lanzas numToRounda un entero, pero ya es un entero. Necesitas convertir a doblar antes de la división, y volver a int después de la multiplicación.

Por último, ¿qué quieres para los números negativos? Redondear "hacia arriba" puede significar redondear a cero (redondear en la misma dirección que los números positivos) o alejarse de cero (un número negativo "mayor"). O tal vez no te importa.

Aquí hay una versión con las tres primeras correcciones, pero no trato el problema negativo:

int roundUp(int numToRound, int multiple)
{
 if(multiple == 0)
 {
  return 0;
 }
 else if(numToRound % multiple == 0)
 {
  return numToRound
 }

 int roundDown = (int) (( (double) numToRound / multiple ) * multiple);
 int roundUp = roundDown + multiple; 
 int roundCalc = roundUp;
 return (roundCalc);
}

@Peter ¿Lo es? Supuse que int / intdevolvería un int, que no es lo que queríamos.
Mike Caron el

int / int de hecho devuelve un int, pero eso es precisamente lo que quieres. Por ejemplo, numToRound = 7, multiple = 3. 7/3 = 2.
Peter Ruderman

4

Redondear al poder de dos:

En caso de que alguien necesite una solución para números positivos redondeados al múltiplo más cercano de una potencia de dos (porque así es como terminé aquí):

// number: the number to be rounded (ex: 5, 123, 98345, etc.)
// pow2:   the power to be rounded to (ex: to round to 16, use '4')
int roundPow2 (int number, int pow2) {
    pow2--;                     // because (2 exp x) == (1 << (x -1))
    pow2 = 0x01 << pow2;

    pow2--;                     // because for any
                                //
                                // (x = 2 exp x)
                                //
                                // subtracting one will
                                // yield a field of ones
                                // which we can use in a
                                // bitwise OR

    number--;                   // yield a similar field for
                                // bitwise OR
    number = number | pow2;
    number++;                   // restore value by adding one back

    return number;
}

El número de entrada permanecerá igual si ya es un múltiplo.

Aquí está la salida x86_64 que GCC da con -O2o -Os(9Sep2013 Build - godbolt GCC en línea):

roundPow2(int, int):
    lea ecx, [rsi-1]
    mov eax, 1
    sub edi, 1
    sal eax, cl
    sub eax, 1
    or  eax, edi
    add eax, 1
    ret

Cada línea de código C corresponde perfectamente con su línea en el ensamblaje: http://goo.gl/DZigfX

Cada una de esas instrucciones es extremadamente rápida , por lo que la función también es extremadamente rápida. Dado que el código es tan pequeño y rápido, puede ser útil para inlinela función al usarlo.


Crédito:


1
Exactamente lo que estaba buscando. ¡Gracias!
kiyo

1
int roundUpPow2 (int num, int pow2) {return num + (pow2 - 1) & ~ (pow2 - 1); } es aproximadamente un 30% más rápido y más fácil de usar (pasa 16 no 4 para redondear al siguiente múltiplo de 16.
Axel Rietschin

3

Estoy usando:

template <class _Ty>
inline _Ty n_Align_Up(_Ty n_x, _Ty n_alignment)
{
    assert(n_alignment > 0);
    //n_x += (n_x >= 0)? n_alignment - 1 : 1 - n_alignment; // causes to round away from zero (greatest absolute value)
    n_x += (n_x >= 0)? n_alignment - 1 : -1; // causes to round up (towards positive infinity)
    //n_x += (_Ty(-(n_x >= 0)) & n_alignment) - 1; // the same as above, avoids branch and integer multiplication
    //n_x += n_alignment - 1; // only works for positive numbers (fastest)
    return n_x - n_x % n_alignment; // rounds negative towards zero
}

y para poderes de dos:

template <class _Ty>
bool b_Is_POT(_Ty n_x)
{
    return !(n_x & (n_x - 1));
}

template <class _Ty>
inline _Ty n_Align_Up_POT(_Ty n_x, _Ty n_pot_alignment)
{
    assert(n_pot_alignment > 0);
    assert(b_Is_POT(n_pot_alignment)); // alignment must be power of two
    -- n_pot_alignment;
    return (n_x + n_pot_alignment) & ~n_pot_alignment; // rounds towards positive infinity (i.e. negative towards zero)
}

Tenga en cuenta que ambos valores negativos redondos hacia cero (eso significa redondear a infinito positivo para todos los valores), ninguno de ellos se basa en el desbordamiento firmado (que no está definido en C / C ++).

Esto da:

n_Align_Up(10, 100) = 100
n_Align_Up(110, 100) = 200
n_Align_Up(0, 100) = 0
n_Align_Up(-10, 100) = 0
n_Align_Up(-110, 100) = -100
n_Align_Up(-210, 100) = -200
n_Align_Up_POT(10, 128) = 128
n_Align_Up_POT(130, 128) = 256
n_Align_Up_POT(0, 128) = 0
n_Align_Up_POT(-10, 128) = 0
n_Align_Up_POT(-130, 128) = -128
n_Align_Up_POT(-260, 128) = -256

He estado usando tu n_Align_Up_POTdesde que lo vi dentro de la clase TList de Delphi. Tiene sus restricciones, como que la alineación (múltiple) es una potencia de 2, pero eso rara vez es un problema porque lo uso principalmente para obtener / verificar la alineación correcta para SMID. Es increíble y parece que no mucha gente lo sabe.
user1593842

2

Probablemente sea más seguro lanzarlo a flotadores y usar ceil (), a menos que sepa que la división int producirá el resultado correcto.


1
Tenga en cuenta que double solo puede contener 54 bits de significado en máquinas basadas en x86. Si tiene entradas de 64 bits, finalmente fallará.
los cerdos

El doble estándar IEEE754 no puede, pero los cpus x64 tienen un punto flotante interno de 80 bits, por lo que las operaciones en un solo número son confiables
Martin Beckett

1
Si bien eso es cierto, usted tiene muy poco control sobre ese redondeo desde C / C ++. Depende de la configuración de las palabras de control y en realidad puede redondear a menos de 80 bits. También tiene SSE y otros conjuntos de instrucciones SIMD que no tienen ese intermedio extendido (el compilador de vectorización podría usarlos fácilmente).
los cerdos

2
int noOfMultiples = int((numToRound / multiple)+0.5);
return noOfMultiples*multiple

C ++ redondea cada número hacia abajo, por lo que si agrega 0.5 (si es 1.5 será 2) pero 1.49 será 1.99, por lo tanto, 1.

EDITAR: lo siento, no vi que deseaba redondear, sugeriría usar un método ceil () en lugar del +0.5


2

bueno para empezar, ya que realmente no entiendo lo que quieres hacer, las líneas

int roundUp = roundDown + multiple;
int roundCalc = roundUp;
return (roundCalc); 

definitivamente podría acortarse a

int roundUp = roundDown + multiple;
return roundUp;

2

puede ser esto puede ayudar:

int RoundUpToNearestMultOfNumber(int val, int num)
{
  assert(0 != num);
  return (floor((val + num) / num) * num);
}

¿Por qué usar floor y la división de enteros? No hay nada al piso. Si fuera doble, al menos podría heredar el manejo de valores negativos.
los cerdos

2

Para redondear siempre

int alwaysRoundUp(int n, int multiple)
{
    if (n % multiple != 0) {
        n = ((n + multiple) / multiple) * multiple;

        // Another way
        //n = n - n % multiple + multiple;
    }

    return n;
}

alwaysRoundUp (1, 10) -> 10

alwaysRoundUp (5, 10) -> 10

alwaysRoundUp (10, 10) -> 10


Para redondear siempre

int alwaysRoundDown(int n, int multiple)
{
    n = (n / multiple) * multiple;

    return n;
}

alwaysRoundDown (1, 10) -> 0

alwaysRoundDown (5, 10) -> 0

alwaysRoundDown (10, 10) -> 10


Para redondear la forma normal

int normalRound(int n, int multiple)
{
    n = ((n + multiple/2)/multiple) * multiple;

    return n;
}

normalRound (1, 10) -> 0

normalRondo (5, 10) -> 10

normalRondo (10, 10) -> 10


2

Redondear al múltiplo más cercano que resulta ser una potencia de 2

unsigned int round(unsigned int value, unsigned int multiple){
    return ((value-1u) & ~(multiple-1u)) + multiple;
}

Esto puede ser útil cuando se asigna a lo largo de líneas de caché, donde el incremento de redondeo que desea es una potencia de dos, pero el valor resultante solo necesita ser un múltiplo de él. En gccel cuerpo de esta función genera 8 instrucciones de ensamblaje sin división ni ramas.

round(  0,  16) ->   0
round(  1,  16) ->  16
round( 16,  16) ->  16
round(257, 128) -> 384 (128 * 3)
round(333,   2) -> 334

1

Encontré un algoritmo que es algo similar a uno publicado anteriormente:

int [(| x | + n-1) / n] * [(nx) / | x |], donde x es un valor de entrada del usuario y n es el múltiplo que se está utilizando.

Funciona para todos los valores x, donde x es un número entero (positivo o negativo, incluido cero). Lo escribí específicamente para un programa C ++, pero esto básicamente se puede implementar en cualquier lenguaje.


1

Para numToRound negativo:

Debería ser realmente fácil hacer esto, pero el módulo estándar% operator no maneja números negativos como uno podría esperar. Por ejemplo -14% 12 = -2 y no 10. Lo primero que debe hacer es obtener un operador de módulo que nunca devuelva números negativos. Entonces roundUp es realmente simple.

public static int mod(int x, int n) 
{
    return ((x % n) + n) % n;
}

public static int roundUp(int numToRound, int multiple) 
{
    return numRound + mod(-numToRound, multiple);
}

1

Esto es lo que haría:

#include <cmath>

int roundUp(int numToRound, int multiple)
{
    // if our number is zero, return immediately
   if (numToRound == 0)
        return multiple;

    // if multiplier is zero, return immediately
    if (multiple == 0)
        return numToRound;

    // how many times are number greater than multiple
    float rounds = static_cast<float>(numToRound) / static_cast<float>(multiple);

    // determine, whether if number is multiplier of multiple
    int floorRounds = static_cast<int>(floor(rounds));

    if (rounds - floorRounds > 0)
        // multiple is not multiplier of number -> advance to the next multiplier
        return (floorRounds+1) * multiple;
    else
        // multiple is multiplier of number -> return actual multiplier
        return (floorRounds) * multiple;
}

El código puede no ser óptimo, pero prefiero un código limpio que un rendimiento en seco.


Lanzar el intto floatpierde fácilmente la precisión y genera respuestas incorrectas.
chux - Restablece a Mónica el

1
int roundUp (int numToRound, int multiple)
{
  return multiple * ((numToRound + multiple - 1) / multiple);
}

a pesar de que:

  • no funcionará para números negativos
  • no funcionará si numRound + desbordamientos múltiples

sugeriría usar enteros sin signo en su lugar, lo que ha definido un comportamiento de desbordamiento.

Obtendrá una excepción es múltiple == 0, pero de todos modos no es un problema bien definido en ese caso.


1

C:

int roundUp(int numToRound, int multiple)
{
  return (multiple ? (((numToRound+multiple-1) / multiple) * multiple) : numToRound);
}

y para tu ~ / .bashrc:

roundup()
{
  echo $(( ${2} ? ((${1}+${2}-1)/${2})*${2} : ${1} ))
}

1

Utilizo una combinación de módulo para anular la adición del resto si xya es un múltiplo:

int round_up(int x, int div)
{
    return x + (div - x % div) % div;
}

Encontramos el inverso del resto y luego el módulo que con el divisor nuevamente para anularlo si es el divisor mismo y luego sumar x.

round_up(19, 3) = 21

1

Aquí está mi solución basada en la sugerencia del OP y los ejemplos dados por todos los demás. Como la mayoría de la gente lo buscaba para manejar números negativos, esta solución hace exactamente eso, sin el uso de funciones especiales, es decir, abdominales y similares.

Al evitar el módulo y usar la división, el número negativo es un resultado natural, aunque se redondea hacia abajo. Después de calcular la versión redondeada hacia abajo, realiza los cálculos necesarios para redondear, ya sea en dirección negativa o positiva.

También tenga en cuenta que no se utilizan funciones especiales para calcular nada, por lo que hay un pequeño aumento de velocidad allí.

int RoundUp(int n, int multiple)
{
    // prevent divide by 0 by returning n
    if (multiple == 0) return n;

    // calculate the rounded down version
    int roundedDown = n / multiple * multiple;

    // if the rounded version and original are the same, then return the original
    if (roundedDown == n) return n;

    // handle negative number and round up according to the sign
    // NOTE: if n is < 0 then subtract the multiple, otherwise add it
    return (n < 0) ? roundedDown - multiple : roundedDown + multiple;
}

Falla con RoundUp(INT_MIN, -1)como n / multiplees intel desbordamiento.
chux - Restablece a Mónica el

1

Creo que esto debería ayudarte. He escrito el siguiente programa en C.

# include <stdio.h>
int main()
{
  int i, j;
  printf("\nEnter Two Integers i and j...");
  scanf("%d %d", &i, &j);
  int Round_Off=i+j-i%j;
  printf("The Rounded Off Integer Is...%d\n", Round_Off);
  return 0;
}

0
/// Rounding up 'n' to the nearest multiple of number 'b'.
/// - Not tested for negative numbers.
/// \see http://stackoverflow.com/questions/3407012/
#define roundUp(n,b) ( (b)==0 ? (n) : ( ((n)+(b)-1) - (((n)-1)%(b)) ) )

/// \c test->roundUp().
void test_roundUp() {   
    // yes_roundUp(n,b) ( (b)==0 ? (n) : ( (n)%(b)==0 ? n : (n)+(b)-(n)%(b) ) )
    // yes_roundUp(n,b) ( (b)==0 ? (n) : ( ((n + b - 1) / b) * b ) )

    // no_roundUp(n,b) ( (n)%(b)==0 ? n : (b)*( (n)/(b) )+(b) )
    // no_roundUp(n,b) ( (n)+(b) - (n)%(b) )

if (true) // couldn't make it work without (?:)
{{  // test::roundUp()
    unsigned m;
                { m = roundUp(17,8); } ++m;
    assertTrue( 24 == roundUp(17,8) );
                { m = roundUp(24,8); }
    assertTrue( 24 == roundUp(24,8) );

    assertTrue( 24 == roundUp(24,4) );
    assertTrue( 24 == roundUp(23,4) );
                { m = roundUp(23,4); }
    assertTrue( 24 == roundUp(21,4) );

    assertTrue( 20 == roundUp(20,4) );
    assertTrue( 20 == roundUp(19,4) );
    assertTrue( 20 == roundUp(18,4) );
    assertTrue( 20 == roundUp(17,4) );

    assertTrue( 17 == roundUp(17,0) );
    assertTrue( 20 == roundUp(20,0) );
}}
}

0

Esto está obteniendo los resultados que busca para enteros positivos:

#include <iostream>
using namespace std;

int roundUp(int numToRound, int multiple);

int main() {
    cout << "answer is: " << roundUp(7, 100) << endl;
    cout << "answer is: " << roundUp(117, 100) << endl;
    cout << "answer is: " << roundUp(477, 100) << endl;
    cout << "answer is: " << roundUp(1077, 100) << endl;
    cout << "answer is: " << roundUp(52,20) << endl;
    cout << "answer is: " << roundUp(74,30) << endl;
    return 0;
}

int roundUp(int numToRound, int multiple) {
    if (multiple == 0) {
        return 0;
    }
    int result = (int) (numToRound / multiple) * multiple;
    if (numToRound % multiple) {
        result += multiple;
    } 
    return result;
}

Y aquí están los resultados:

answer is: 100
answer is: 200
answer is: 500
answer is: 1100
answer is: 60
answer is: 90

0

Creo que esto funciona:

int roundUp(int numToRound, int multiple) {
    return multiple? !(numToRound%multiple)? numToRound : ((numToRound/multiple)+1)*multiple: numToRound;
}

-1

Esto funciona para mí pero no traté de manejar los negativos

public static int roundUp(int numToRound, int multiple) {
    if (multiple == 0) {
        return 0;
    } else if (numToRound % multiple == 0) {
    return numToRound;
    }

    int mod = numToRound % multiple;
    int diff = multiple - mod;
    return numToRound + diff;
}

-3

Aquí hay una solución súper simple para mostrar el concepto de elegancia. Básicamente es para instantáneas de cuadrícula.

(pseudocódigo)

nearestPos = Math.Ceil( numberToRound / multiple ) * multiple;

¿comprobaste tu idea antes de enviarla? no da una respuesta
correcta

Eso ni siquiera es un código válido.
user13783520
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.