C ++ : 가장 가까운 수의 배수로 올림


168

OK-기본 질문처럼 보일 정도로 여기에 게시하는 것이 거의 창피합니다 (누군가가 투표를 마치면 삭제하겠습니다).

이것이 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

3
논리에 오류가 있습니다. 4를 2의 가장 가까운 배수로 반올림한다고 가정합니다. roundDown = (4/2) * 2 = 4; 올림 = 4 + 2; 그래서 roundCalc = 6입니다.이 경우 4를 반환한다고 가정합니다.
— Niki Yoshiuchi

roundUp (30,30)에서는 작동하지 않습니다. 60은 답변으로, 30은 답변으로 제공해야합니다.
— bsobaid

@bsobaid : 하단에서 내 답변을 확인하십시오.
— Niklas B.

3
테스트 케이스는 음수, 나눗셈이 정확한 경우, 나눗셈이 거의 정확한 경우 및 숫자가 범위의 한계에 매우 가까운 경우를 포함하는 예제가 눈에 띄지 int않습니다.

1
Robben_Ford_Fan_boy, 당신이 간 답을 가진 편집은 제거되어야합니다. 주어진 답변과 다른 경우 자신의 답변을 게시 할 수 있습니다. 이 답변에는 답변 섹션에서 해결해야 할 문제가 있습니다.
— chux-복원 Monica Monica

답변:


161

음수에 대해 확실하지 않은 양수에 작동합니다. 정수 수학 만 사용합니다.

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

+1 제 생각에는 가장 훌륭하고 읽기 쉬운 솔루션입니다.
— Robben_Ford_Fan_boy

1
if(number<0){ multiple = multiple*(-1); }음수를 올바른 방향으로 반올림하기 시작할 때 추가
— Josh

4
@ 조쉬 : 왜 곱셈을 사용 하는가? if(number<0) multiple = -multiple더 쉽습니다.
— md5

roundUp (30,30)에서는 작동하지 않습니다. 60을 답변으로 제공하지만 30을 답변으로 제공해야합니다.
— bsobaid

@bsobaid 불가능합니다. if (remainder == 0)시험은이 경우의주의를 기울여야한다. 그것은 나를 위해 작동합니다 : ideone.com/Waol7B
— Mark Ransom

112

조건없이 :

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

이것은 0에서 반올림하는 것처럼 작동 합니다.음수의 경우

편집 : 음수에도 작동하는 버전

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

테스트


multiple2의 거듭 제곱 인 경우 (~ 3.7 배 빠름 http://quick-bench.com/sgPEZV9AUDqtx2uujRSa3-eTE80 )

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

테스트


24
2 버전의 거듭 제곱은 +1입니다. 곱셈, 나눗셈 또는 모듈로의 비용을 완전히 피할 수 있으므로 매우 유용합니다.
— Nikos C.

이 알고리즘에 전제 조건이없는 것입니까? 음수는 어떻습니까? 동작은 C ++ 11 이전에 정의되지 않은 것으로 보입니다 .
— cubuspl42

> 음수는 어떻습니까? 설명한 바와 같이, 이것은 0에서 반올림하는 것과 같은 음수에 적용됩니다.
— KindDragon

"반올림"은 0에서 반올림하지 않고 양의 무한대로 반올림하는 것을 의미합니다.

8
주 & ~(x - 1)와 동일한 & -x2의 보수 연산합니다.
— Todd Lehman

39

요인이 항상 긍정적일 때 작동합니다.

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

편집 :이 반환합니다 round_up(0,100)=100. 를 반환하는 솔루션에 대해서는 아래의 Paul 의견을 참조하십시오 round_up(0,100)=0.


1
'다수의'사건을 처리하는 가장 짧은 경우처럼 보입니다.
— harningt

1
비용이 많이 드는 작업 수 측면에서 최상의 솔루션입니다. 단일 분할 만 사용하고 곱셈은 사용하지 않습니다
— Niklas B.

3
허용 된 답변 에서처럼 0 대신에 round_up (0, 100) == 100
— Gregory

7
그렇지 num + factor - 1 - (num + factor - 1) % factor않습니까?
— Paul

6
num - 1 - (num - 1) % factor + factor정수 오버플로의 위험없이 동일한 계산을 수행합니다.

24

이것은 "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
}

1
이것은 숫자의 다음 배수로 반올림되지 않습니다.
— aaaa bbbb

7
roundTo가 2의 거듭 제곱 일 경우 / 및 *를 제거하고 저렴한 연산만으로 끝날 수 있기 때문에이 솔루션이 마음에 듭니다 (x = roundTo-1; return (n + x) & ~ x;)
— Trejkaz

@Trejkaz nope. (x = roundTo - 1; return (n+x)&~roundTo;)내 대답과 같아야합니다
— KindDragon

@KindDragon 나에게 잘못된 결과를 생성하지만 ~ roundTo 대신 ~ x라고 수정하면 예상 결과가 나타납니다. 어쨌든 Java 8에서.
— Trejkaz

@KindDragon : AND 마스크는 이거나 0xFFF...000그렇지 않아야 0xFFF7FFF합니다. 따라서 2의 -거듭 제곱에서 2의 보수 부정 ( : 빼기) 또는 2의 거듭 제곱보다 작은 비트 플립 (1의 보수 역, ~: 틸드)을 원합니다. 빼기). 그래서 (n+x) & ~x나 (n-roundTo+1) & -roundTo.
— Peter Cordes

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

조건을 뒤섞을 필요가 없습니다.


11

짧고 달콤한 답변을 찾는 사람에게. 이것이 내가 사용한 것입니다. 부정에 대한 설명이 없습니다.

n - (n % r)

이전 요소를 반환합니다.

(n + r) - (n % r)

다음을 반환합니다. 이것이 누군가를 돕기를 바랍니다. :)


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

이것은 모든 플로트 번호 또는베이스에 적용됩니다 (예 : -4를 가장 가까운 6.75로 반올림 할 수 있음). 본질적으로 고정 소수점으로 변환하고 반올림 한 다음 다시 변환합니다. AWAY를 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;
}

부정적인 입력 지원이 추가 된 플 린스의 대답은 어느 정도입니다.


float roundUp 코드를 두 배로 테스트했는데 나에게 효과적입니다. 내 문제를 정말 해결합니다.
— Ashif

1
무엇에 대한 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); }라운드 반올림하려면 또는 스왑 천장을 만들다.
— Troyseph

8

이것은 float, double, long, int 및 short에서 작동하는 템플릿 함수를 사용하는 최신 c ++ 접근법입니다 (그러나 사용되는 double 값으로 인해 long long 및 long double은 아닙니다).

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

그러나 당신은 쉽게에 대한 지원을 추가 할 수 있습니다 long long하고 long double아래와 같이 템플릿 특수화로 :

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

반올림 할 함수를 만들려면 std::ceil및를 반올림하여 사용하십시오 std::floor. 위의 예는을 사용하여 반올림 std::round합니다.

아래와 같이 "라운드 업"또는 "라운드 실링"템플릿 기능으로 잘 알려져 있습니다.

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

아래와 같이 "라운드 다운"또는 "라운드 플로어"템플릿 기능으로 잘 알려져 있습니다.

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
더하기 1이지만, 어떤 사람들은 여러 == 0
— 공명

3
int64_t를 double로 변환하면 손실이 발생할 수 있으므로 일반적인 형식은 아닙니다.
— Adrian McCarthy

@AdrianMcCarthy 예, 위와 같이 올바른 템플릿 전문화를 만들어야합니다. 보다시피, long long와에 대한 두 가지 추가 기능을 구현 long double합니다. 다른 두 기능에 대해서도 동일하게 수행해야합니다.
— 플 로브 디스

나는 이것이 가장 느리다고 생각하지만 반드시 그럴 필요는 없습니다. std :: enable_if_t를 수행하고 정수와 부동 소수점에 대해 두 개의 분기를 수행하기 만하면됩니다. numeric_limits를 더 잘 사용하고 가수가 실제로 값에 맞도록 충분히 큰지 확인할 수 있습니다. 그것은 안전에 추가 될 것입니다.
— 돼지

5

우선, 오류 조건 (multiple == 0)은 아마도 반환 값을 가져야합니다. 뭐? 모르겠어요 아마도 예외를 던지고 싶을 수도 있습니다. 그러나 아무것도 돌려주는 것은 위험하지 않습니다.

둘째, numToRound가 이미 배수가 아닌지 확인해야합니다. 그렇지 않으면에 추가 multiple할 때 roundDown오답이 표시됩니다.

셋째, 캐스트가 잘못되었습니다. numToRound정수로 캐스트 했지만 이미 정수입니다. 나누기 전에 두 배로 캐스팅하고 곱셈 후에 다시 int로 캐스팅해야합니다.

마지막으로 음수로 무엇을 원하십니까? 반올림 "위"는 0으로 반올림하거나 (양수와 같은 방향으로 반올림) 또는 0에서 멀어짐 ( "더 큰"음수)을 의미 할 수 있습니다. 아니면 신경 쓰지 않을 수도 있습니다.

다음은 처음 세 가지 수정 사항이있는 버전이지만 부정적인 문제는 다루지 않습니다.

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

@ 피터인가요? 나는 그것이 int / intint를 반환 한다고 가정했는데 , 이것은 우리가 원하는 것이 아닙니다.
— Mike Caron

int / int는 실제로 int를 반환하지만 정확히 원하는 것입니다. 예를 들어, numToRound = 7, 배수 = 3. 7 / 3 = 2입니다.
— Peter Ruderman

4

2의 거듭 제곱으로 반올림 :

누군가가 2의 거듭 제곱의 가장 가까운 배수로 반올림 한 양수에 대한 솔루션이 필요한 경우를 대비하여 (내가 여기서 끝났기 때문에) :

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

입력 번호가 이미 여러 개인 경우 입력 번호는 그대로 유지됩니다.

다음은 GCC가 제공하는 x86_64 출력 -O2또는 -Os(9Sep2013 Build-godbolt GCC online)입니다.

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

각 C 코드 줄은 어셈블리의 해당 줄과 완벽하게 일치합니다. http://goo.gl/DZigfX

각 명령어는 매우 빠르 므로 기능도 매우 빠릅니다. 코드가 너무 작고 빠르기 때문에 코드를 inline사용할 때이 기능 이 유용 할 수 있습니다 .


신용:


1
정확히 내가 찾던 것. 감사!
— kiyo

1
int roundUpPow2 (int num, int pow2) {return num + (pow2-1) & ~ (pow2-1); } 빠른 30 %에 대해, 그리고 사용하기 쉬운 (당신은 (16)의 다음 배수로 올림 (4) (16)을하지 통과
— 악셀 Rietschin

3

나는 사용하고있다 :

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
}

그리고 2의 거듭 제곱 :

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

음수 값을 모두 0으로 반올림하면 (즉, 모든 값에 대해 양의 무한대로 반올림 됨) 서명 된 오버플로 (C / C ++에서 정의되지 않음)에 의존하지 않습니다.

이것은 다음을 제공합니다.

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

n_Align_Up_POT델파이의 TList 클래스에서 본 이후로 귀하의 사용을 해왔습니다 . 정렬 (여러)이 2의 거듭 제곱과 같은 제한 사항이 있지만 SMID에 대한 올바른 정렬을 얻거나 확인하는 데 주로 사용하기 때문에 거의 문제가되지 않습니다. 그것은 굉장하며 많은 사람들이 그것에 대해 알지 못하는 것 같습니다.
— user1593842

2

int 디비전이 올바른 결과를 생성한다는 것을 알지 못하면 float로 캐스팅하고 ceil ()을 사용하는 것이 더 안전합니다.


1
x86 기반 시스템에서는 double이 54 비트의 유효 값 만 보유 할 수 있습니다. 64 비트 정수가 있으면 결국 실패합니다.
— 돼지

IEEE754 표준 double은 불가능하지만 x64 CPU는 80 비트 내부 부동 소수점을 가지므로 단일 숫자에서의 작동이 안정적입니다.
— Martin Beckett

1
사실이지만 C / C ++에서 반올림을 거의 제어 할 수 없습니다. 제어 단어 설정에 따라 다르며 실제로 80 비트 미만으로 반올림 할 수 있습니다. 또한 SSE 및 기타 SIMD 명령어 세트에는 확장 된 중간체가 없습니다 (벡터화 컴파일러에서 쉽게 사용할 수 있음).
— 돼지

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

C ++은 각 숫자를 반올림하므로 0.5를 추가하면 (1.5 인 경우 2) 1.49는 1.99이므로 1입니다.

편집-죄송합니다 반올림하고 싶지 않아 + 0.5 대신 ceil () 메서드를 사용하는 것이 좋습니다


2

글쎄, 당신이하고 싶은 것을 정말로 이해하지 못하기 때문에, 라인

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

확실히 단축 될 수

int roundUp = roundDown + multiple;
return roundUp;

2

이것이 도움이 될 수 있습니다.

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

왜 바닥과 정수 나누기를 사용합니까? 바닥에 아무것도 없습니다. 두 배인 경우 최소한 음수 처리를 상속 할 수 있습니다.
— 돼지

2

항상 반올림

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


항상 반올림

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

    return n;
}

alwaysRoundDown (1, 10)-> 0

alwaysRoundDown (5, 10)-> 0

alwaysRoundDown (10, 10)-> 10


정상적인 방법으로 반올림

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

    return n;
}

normalRound (1, 10)-> 0

normalRound (5, 10)-> 10

normalRound (10, 10)-> 10


2

2의 거듭 제곱 인 가장 가까운 배수로 반올림

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

이것은 원하는 반올림 증분이 2의 거듭 제곱 인 캐시 라인을 따라 할당 할 때 유용 할 수 있지만 결과 값은 그 배수 만 필요합니다. 일 gcc함수의 본체와 분할 또는 분기 8 개 어셈블리 명령어를 생성한다.

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

1

위에 게시 된 것과 다소 비슷한 알고리즘을 발견했습니다.

int [(| x | + n-1) / n] * [(nx) / | x |], 여기서 x는 사용자 입력 값이고 n은 사용중인 배수입니다.

모든 값 x에서 작동합니다. 여기서 x는 정수입니다 (양수 또는 음수, 0 포함). C ++ 프로그램을 위해 특별히 작성했지만 기본적으로 모든 언어로 구현할 수 있습니다.


1

음수 numToRound의 경우 :

이 작업을 수행하는 것이 쉽지만 표준 모듈로 % 연산자는 예상과 같이 음수를 처리하지 않습니다. 예를 들어 -14 % 12 = -2이고 10이 아닙니다. 가장 먼저해야 할 일은 음수를 반환하지 않는 모듈로 연산자를 얻는 것입니다. 그러면 올림은 정말 간단합니다.

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

이것이 내가 할 일입니다.

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

코드가 최적은 아니지만 건조 성능보다 깨끗한 코드를 선호합니다.


를 캐스팅하면 정밀도 int가 float쉽게 떨어지고 오답을 만듭니다.
— chux-복원 Monica Monica

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

이기는 하지만:

  • 음수에는 작동하지 않습니다
  • numRound + 다중 오버플로 인 경우 작동하지 않습니다

대신 부호없는 정수를 사용하는 것이 좋습니다. 오버플로 동작을 정의했습니다.

배수 == 0이라는 예외가 있지만 어쨌든 잘 정의 된 문제는 아닙니다.


1

씨:

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

~ / .bashrc의 경우 :

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

1

x이미 여러 배인 경우 나머지의 추가를 무효화하기 위해 모듈러스 조합을 사용합니다 .

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

우리는 나머지의 역수를 구한 다음, 제수 자체가 있다면 제수를 사용하여 다시 무효화하는 계수를 추가 x합니다.

round_up(19, 3) = 21

1

다음은 OP의 제안과 다른 사람들이 제시 한 예를 기반으로 한 솔루션입니다. 대부분의 사람들이 음수를 처리하기 위해 찾고 있었기 때문에이 솔루션은 특별한 기능 (예 : abs 등)을 사용하지 않고 바로 그 기능을 수행합니다.

모듈러스를 피하고 나눗셈을 대신 사용하면 음수가 반올림되지만 자연스런 결과입니다. 반올림 된 버전이 계산 된 후에는 음수 또는 양수 방향으로 반올림하는 데 필요한 수학이 수행됩니다.

또한 아무것도 계산하는 데 특별한 기능이 사용되지 않으므로 속도가 약간 향상됩니다.

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

실패 RoundUp(INT_MIN, -1)로 n / multiple입니다 int오버 플로우.
— chux-복원 Monica Monica

1

나는 이것이 당신을 도울 것이라고 생각합니다. 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

이것은 양의 정수를 찾고있는 결과를 얻습니다.

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

출력은 다음과 같습니다.

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

0

나는 이것이 효과가 있다고 생각한다.

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

-1

이것은 나를 위해 작동하지만 부정적인 것을 처리하려고하지 않았습니다

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

-2

다음은 우아함의 개념을 보여주는 매우 간단한 솔루션입니다. 기본적으로 그리드 스냅 용입니다.

(의사 코드)

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

제출하기 전에 아이디어를 확인 했습니까? 그것은 정확한 답변을
— yaodav

그것은 유효한 코드조차 아닙니다.
— user13783520
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.