C ++: Округление до ближайшего кратного числа

Хорошо - мне почти неловко размещать это здесь (и я удалю, если кто-нибудь проголосует за закрытие), поскольку это кажется основным вопросом.

Это правильный способ округления числа до кратного в C ++?

Я знаю, что есть и другие вопросы, связанные с этим, но мне особенно интересно узнать, как лучше всего это сделать в 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);
}

Обновление: Извините, я, вероятно, не разъяснил намерение. Вот несколько примеров:

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
154
задан Josh Lee 24 June 2019 в 19:07
поделиться

8 ответов

Это работает для положительных чисел, не уверен в отрицательных. Он использует только целочисленную математику.

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

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

    return numToRound + multiple - remainder;
}

Изменить: вот версия, которая работает с отрицательными числами, если под «вверх» вы подразумеваете результат, который всегда> = ввод.

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;
}
149
ответ дан 23 November 2019 в 21:59
поделиться
int noOfMultiples = int((numToRound / multiple)+0.5);
return noOfMultiples*multiple

C ++ округляет каждое число в меньшую сторону, поэтому если вы добавите 0,5 (если 1,5, то будет 2), но 1,49 будет 1,99, следовательно, 1.

РЕДАКТИРОВАТЬ - Извините, вы не заметили, что вы хотели чтобы округлить, я бы предложил использовать метод ceil () вместо +0,5

2
ответ дан 23 November 2019 в 21:59
поделиться

Вероятно, безопаснее привести к типу float и использовать ceil () - если вы не знаете, что деление int даст правильный результат.

2
ответ дан 23 November 2019 в 21:59
поделиться

Во-первых, ваше условие ошибки (несколько == 0), вероятно, должно иметь возвращаемое значение. Какие? Я не знаю. Может быть, вы хотите создать исключение, решать вам. Но возвращать ничего не опасно.

Во-вторых, вы должны проверить, что numToRound еще не является кратным. В противном случае, когда вы добавите несколько к roundDown , вы получите неправильный ответ.

В-третьих, ваши слепки неверны. Вы приводите numToRound к целому числу, но это уже целое число. Вам нужно привести к удвоению до деления и обратно к int после умножения.

Наконец, что вы хотите от отрицательных чисел? Округление «вверх» может означать округление до нуля (округление в том же направлении, что и положительные числа) или от нуля («большее» отрицательное число). Или, может быть, тебе все равно.

Вот версия с первыми тремя исправлениями, но я не занимаюсь отрицательной проблемой:

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);
}
5
ответ дан 23 November 2019 в 21:59
поделиться
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;
}

Это работает для любого плавающего числа или основания (например, вы можете округлить -4 до ближайшего 6,75). По сути, это преобразование в фиксированную точку, округление, а затем обратное преобразование. Она обрабатывает отрицательные значения, округляя НАПРЯМУЮ от 0. Она также обрабатывает отрицательное округление до значения, превращая функцию в roundDown.

Версия для int выглядит так:

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;
}

Что более или менее похоже на ответ Плинта, с добавленной поддержкой отрицательного ввода.

9
ответ дан 23 November 2019 в 21:59
поделиться

Это обобщение проблемы «как мне узнать, сколько байтов займет n битов? (A: (n бит + 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
}
22
ответ дан 23 November 2019 в 21:59
поделиться

с одной стороны, так как я действительно не понимаю, что вы хотите сделать, строки

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

определенно можно сократить до

int roundUp = roundDown + multiple;
return roundUp;
2
ответ дан 23 November 2019 в 21:59
поделиться
int roundUp(int numToRound, int multiple)
{
 if(multiple == 0)
 {
  return 0;
 }
 return ((numToRound - 1) / multiple + 1) * multiple;  
}

И не нужно возиться с условиями

14
ответ дан 23 November 2019 в 21:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: