C ++: किसी संख्या के निकटतम गुणक तक गोलाई


168

ठीक है - मैं लगभग इसे यहाँ पोस्ट करने से शर्मिंदा हूँ (और अगर किसी को वोट देना है तो मैं इसे हटा दूंगा) क्योंकि यह एक मूल प्रश्न लगता है।

क्या 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 को गोल करना चाहता हूं। (4/2) * 2 = 4; राउंडअप = 4 + 2; so roundCalc = 6. मैं मान रहा हूं कि आप उस स्थिति में 4 लौटना चाहेंगे।
निकी योशीचुकी

यह राउंडअप (30,30) के लिए काम नहीं करता है। यह उत्तर के रूप में 60 देता है, इसे अभी भी 30 को उत्तर के रूप में देना चाहिए ..
bsobaid

@bsobaid: नीचे मेरे जवाब की जाँच करें। यहां अन्य समाधानों की तुलना में यह थोड़ा सरल है, हालांकि उन लोगों को भी काम करना चाहिए
निकोल्स बी।

3
आपके परीक्षण के मामले निस्संदेह नकारात्मक संख्या वाले उदाहरणों को याद कर रहे हैं, ऐसे मामले जहां विभाजन सटीक है, ऐसे मामले जहां विभाजन लगभग सटीक है, और ऐसे मामले जहां संख्याएं सीमा की सीमा के बहुत निकट हैं int

1
Robben_Ford_Fan_boy, आपके द्वारा गए उत्तर के साथ संपादित हटा दिया जाना चाहिए। यदि यह दिए गए उत्तरों से भिन्न है तो आप अपना उत्तर पोस्ट कर सकते हैं। जैसा कि यह खड़ा है, उस उत्तर में समस्याएं हैं जिन्हें उत्तर अनुभाग में संबोधित किया जाना चाहिए।
चक्स - मोनिका

जवाबों:


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); }शुरू में सही दिशा में दौर ऋणात्मक संख्याओं को
जोश

4
@ जोश: गुणा का उपयोग क्यों? if(number<0) multiple = -multipleसे आसान है।
md5

यह राउंडअप (30,30) के लिए काम नहीं करता है। यह उत्तर के रूप में 60 देता है, फिर भी इसे उत्तर के रूप में 30 देना चाहिए।
bsobaid

@bsobaid नामुमकिन। if (remainder == 0)परीक्षण उस मामले का ध्यान रखना चाहिए। यह मेरे लिए काम करता है: ideone.com/Waol7B
मार्क रैनसम

112

शर्तों के बिना:

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

यह नकारात्मक संख्याओं के लिए शून्य से दूर चक्कर लगाने जैसा काम करता है

संपादित करें: संस्करण जो नकारात्मक संख्याओं के लिए भी काम करता है

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। बहुत उपयोगी के रूप में यह गुणन, विभाजन या मोड्यूलो की लागत से पूरी तरह से बचा जाता है।
निकोस सी।

क्या आप सुनिश्चित हैं कि इन एल्गोरिदम में कोई पूर्व शर्त नहीं है? नकारात्मक संख्याओं के बारे में क्या? व्यवहार पूर्व C ++ 11 में अपरिभाषित प्रतीत होता है
cubuspl42

> नकारात्मक संख्याओं के बारे में क्या? जैसा कि वर्णित है, यह शून्य से दूर गोलाई जैसे नकारात्मक संख्याओं के लिए काम करता है।
१३:१३ पर किण्डरगन

मैंने "राउंडिंग अप" को सकारात्मक अनंत की ओर राउंडिंग के रूप में पढ़ा, शून्य से दूर राउंडिंग नहीं।

8
ध्यान दें कि दो पूरक अंकगणित के लिए & ~(x - 1)समान है & -x
टॉड लेहमन

39

यह काम करता है जब कारक हमेशा सकारात्मक होगा:

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

संपादित करें: यह रिटर्न round_up(0,100)=100। कृपया एक समाधान के लिए नीचे दिए गए पॉल की टिप्पणी देखें round_up(0,100)=0


1
सबसे छोटा मामला लगता है जो 'पहले से ही एक से अधिक' मामले को संभालता है।
12

1
महंगे संचालन की संख्या के संदर्भ में सबसे अच्छा समाधान। यह केवल एकल विभाजन का उपयोग करता है और कोई गुणन नहीं करता है
निकल्स बी

3
राउंड_अप (0, 100) == 100 के बदले 0 के रूप में स्वीकार किए गए उत्तर में
ग्रेगरी

7
यह नहीं होना चाहिए num + factor - 1 - (num + factor - 1) % factor?
पॉल

6
num - 1 - (num - 1) % factor + factorपूर्णांक अतिप्रवाह के जोखिम के बिना एक ही गणना करता है।

24

यह "मुझे कैसे पता चलेगा कि कितने बाइट्स 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
यह किसी संख्या के अगले कई तक नहीं होता है।
आआआआ bbbb

7
मैं इस समाधान की तरह अगर roundTo 2 के एक शक्ति हो जाएगा, आप को खत्म कर सकते हैं क्योंकि / और * और कुछ भी नहीं के साथ खत्म हो लेकिन सस्ते परिचालन (एक्स = roundTo - 1; वापसी (एन + x) और ~ x;)
Trejkaz

@ त्रीजकज नप। यह (x = roundTo - 1; return (n+x)&~roundTo;)मेरे उत्तर में जैसा होना चाहिए
KindDragon

@KindDragon जो मेरे लिए गलत परिणाम उत्पन्न करता है, लेकिन अगर मैं इसे ~ roundTo के बजाय ~ x कहने के लिए सही करता हूं, तो मुझे अपेक्षित परिणाम मिलता है। जावा 8 पर वैसे भी।
तर्जुक

@KindDragon: AND मास्क को होना चाहिए 0xFFF...000, 0xFFF7FFFकुछ होना चाहिए या नहीं , इसलिए आप 2 की -शक्ति पर या तो 2 का पूरक निषेध ( : ऋण) चाहते हैं, या 2 की शक्ति से कम पर एक बिट-फ्लिप (किसी का पूरक व्युत्क्रम ~: tilde) माइनस नहीं)। तो (n+x) & ~xया (n-roundTo+1) & -roundTo
पीटर कॉर्ड्स

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

यह किसी भी फ्लोट नंबर या आधार के लिए काम करता है (उदाहरण के लिए, आप निकटतम ४. .५ पर गोल कर सकते हैं)। संक्षेप में, यह निश्चित बिंदु पर परिवर्तित हो रहा है, वहां गोल हो रहा है, फिर वापस परिवर्तित हो रहा है। यह 0. से AWAY को गोल करके नकारात्मक को संभालता है। यह फ़ंक्शन को अनिवार्य रूप से फ़ंक्शन को राउंडडाउन में बदलकर एक नकारात्मक राउंड को मान देता है।

एक विशिष्ट विशिष्ट संस्करण दिखता है:

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

अतिरिक्त नकारात्मक इनपुट समर्थन के साथ, जो कमोबेश प्लिंथ का उत्तर है।


मैंने डबल के साथ फ्लोट राउंडअप कोड का परीक्षण किया है, यह मेरे लिए काम करता है। वास्तव में मेरे मुद्दे को हल करती है।
आशिफ

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); }गोलाई पाने के लिए राउंड के बारे में या स्वैप सीप क्या है ।
ट्रॉयसेफ

8

यह एक टेम्पलेट फ़ंक्शन का उपयोग करने वाला आधुनिक सी ++ दृष्टिकोण है जो फ्लोट, डबल, लॉन्ग, इंट और शॉर्ट (लेकिन लंबे समय तक और उपयोग किए गए दोहरे मानों के कारण लंबे डबल के लिए नहीं) के लिए काम कर रहा है।

#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, हालांकि कुछ लोगों को यह अधिक
गूंजने वाला

3
खबरदार, क्योंकि int64_t को डबल में बदलना हानिपूर्ण हो सकता है, इसलिए यह टाइप-जेनेरिक नहीं है क्योंकि यह दिखाई दे सकता है।
एड्रियन मैक्कार्थी

@ AdrianMcCarthy हाँ आपको सही टेम्प्लेट स्पेशलाइज़ेशन बनाना होगा जैसा कि ऊपर दिखाया गया है। जैसा कि आप देख सकते हैं, मैं long longऔर के लिए दो अतिरिक्त कार्यों को लागू करता हूं long double। स्पष्ट रूप से अन्य दो कार्यों के लिए भी ऐसा ही किया जाना चाहिए।
फ्लोव्डिस

मुझे लगता है कि यह अब तक का सबसे धीमा है लेकिन ऐसा नहीं होगा। आपको केवल std :: enable_if_t को std और दो पूर्णांक और फ्लोट के लिए करना है। आप न्यूमेरिक_लिमिट्स का बेहतर उपयोग भी कर सकते हैं और देख सकते हैं कि क्या मंटिसा वास्तव में मूल्य फिट करने के लिए पर्याप्त है। यह सुरक्षा के लिए जोड़ देगा।
सूअर

5

सबसे पहले, आपकी त्रुटि स्थिति (एकाधिक == 0) में संभवतः वापसी मान होना चाहिए। क्या? मुझे नहीं पता। शायद आप एक अपवाद फेंकना चाहते हैं, जो आपके ऊपर है। लेकिन, कुछ भी लौटाना खतरनाक नहीं है।

दूसरा, आपको जांचना चाहिए कि numToRound पहले से ही एक बहु नहीं है। अन्यथा, जब आप जोड़ते multipleहैं roundDown, तो आपको गलत उत्तर मिलेगा।

तीसरा, आपकी जातियां गलत हैं। आप numToRoundएक पूर्णांक पर जाते हैं, लेकिन यह पहले से ही पूर्णांक है। आपको विभाजन से पहले डबल करने के लिए कास्ट करने की आवश्यकता है, और गुणा के बाद वापस इंट में जाने की आवश्यकता है।

अंत में, आप नकारात्मक संख्याओं के लिए क्या चाहते हैं? गोलाई "अप" का मतलब शून्य से गोलाई हो सकता है (सकारात्मक दिशाओं के समान दिशा में गोलाई), या शून्य से दूर (एक "बड़ा" नकारात्मक संख्या)। या, शायद आपको परवाह नहीं है।

यहाँ पहले तीन सुधारों के साथ एक संस्करण है, लेकिन मैं नकारात्मक मुद्दे से नहीं निपटता:

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 / intएक इंट वापस आएगा, जो कि हम नहीं चाहते थे।
माइक कारन

int / int वास्तव में एक int लौटाता है, लेकिन यह वही है जो आप चाहते हैं। उदाहरण के लिए, numToRound = 7, multiple = 3. 7/3 = 2.
पीटर रुडरमैन

4

दो की शक्ति के लिए गोल:

बस अगर किसी को दो की शक्ति के निकटतम एकाधिक में गोल संख्या के लिए एक समाधान की आवश्यकता होती है (क्योंकि यह है कि मैं यहाँ कैसे समाप्त हुआ):

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

यदि यह पहले से ही मल्टीपल है तो इनपुट नंबर वही रहेगा।

यहाँ x86_64 आउटपुट है जो GCC देता है -O2या -Os(9Sep2013 बिल्ड - Godbolt GCC ऑनलाइन):

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

कोड की प्रत्येक सी लाइन विधानसभा में अपनी लाइन के साथ पूरी तरह से मेल खाती है: http://goo.gl/DZigfX

उन निर्देशों में से प्रत्येक बहुत तेज़ हैं , इसलिए फ़ंक्शन बहुत तेज़ है। चूंकि कोड इतना छोटा और त्वरित है, इसलिए इसका inlineउपयोग करते समय यह फ़ंक्शन के लिए उपयोगी हो सकता है।


क्रेडिट:


1
ठीक वही जो मेरे द्वारा खोजा जा रहा था। धन्यवाद!
कीयो

1
int roundUpPow2 (int num, int pow2) {वापसी संख्या + (pow2 - 1) & ~ (pow2 - 1); } लगभग 30% तेज, और उपयोग करने में आसान है (आप 16 के अगले कई के लिए गोल करने के लिए 16 नहीं 4 पास करते हैं।
Axel 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
}

और दो की शक्तियों के लिए:

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

ध्यान दें कि दोनों गोल नकारात्मक मानों के प्रति शून्य (जिसका अर्थ है सभी मूल्यों के लिए सकारात्मक अनंत के लिए दौर), दोनों में से कोई भी हस्ताक्षरित अतिप्रवाह (जो सी / सी ++ में अपरिभाषित है) पर निर्भर नहीं करता है।

यह देता है:

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 की शक्ति है, लेकिन यह एक समस्या है क्योंकि मैं ज्यादातर इसका उपयोग एसएमआईडी के लिए सही संरेखण प्राप्त करने / जांचने के लिए करता हूं। यह कमाल है और ऐसा नहीं है कि बहुत से लोग इसके बारे में जानते हैं।
user1593842

2

संभवतः तैरने के लिए डाली और छत () का उपयोग करने के लिए सुरक्षित है - जब तक आप नहीं जानते कि इंट डिवीजन सही परिणाम का उत्पादन करने जा रहा है।


1
ध्यान दें कि डबल केवल x86- आधारित मशीनों पर महत्व के 54 बिट्स को पकड़ सकता है। यदि आपके पास 64-बिट इनट्स हैं, तो यह अंततः विफल हो जाएगा।
सूअर

IEEE754 मानक डबल नहीं हो सकता है, लेकिन x64 cpus में एक 80 बिट आंतरिक फ्लोटिंग बिंदु है, इसलिए एक ही नंबर पर संचालन विश्वसनीय है
मार्टिन बेकेट

1
जबकि यह सच है, सी / सी ++ से उस गोलाई पर आपका बहुत कम नियंत्रण है। यह नियंत्रण शब्द सेटिंग्स पर निर्भर करता है और यह वास्तव में 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 के बजाय एक छत () विधि का उपयोग करने का सुझाव दूंगा


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

हमेशा। 1 (10, 10) -> 10

हमेशापृथक (5, 10) -> 10

हमेशापृच्छा (10, 10) -> 10


हमेशा गोल नीचे की ओर

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

    return n;
}

हमेशाराउंडडाउन (1, 10) -> 0

हमेशाराउंडडाउन (5, 10) -> 0

हमेशाराउंडडाउन (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;
}

यह कैचिल्स के साथ आवंटित करते समय उपयोगी हो सकता है, जहां आप चाहते हैं कि गोलाई वृद्धि दो की शक्ति है, लेकिन परिणामी मूल्य केवल इसके कई होने की आवश्यकता है। 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 एक पूर्णांक (धनात्मक या ऋणात्मक, शून्य सहित) है। मैंने इसे विशेष रूप से C ++ प्रोग्राम के लिए लिखा था, लेकिन इसे मूल रूप से किसी भी भाषा में लागू किया जा सकता है।


1

नकारात्मक अंक के लिए:

ऐसा करना वास्तव में आसान होना चाहिए, लेकिन मानक मोडुलो% ऑपरेटर नकारात्मक संख्याओं को नहीं संभालता है जैसे कि कोई उम्मीद कर सकता है। उदाहरण के लिए -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 -

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

हालांकि:

  • नकारात्मक संख्याओं के लिए काम नहीं करेगा
  • यदि संख्या + एकाधिक ओवरफ्लो हो तो काम नहीं करेगा

इसके बजाय अहस्ताक्षरित पूर्णांक का उपयोग करने का सुझाव देंगे, जिसने अतिप्रवाह व्यवहार को परिभाषित किया है।

आपको एक अपवाद मिलेगा कई == 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

यहाँ ओपी के सुझाव और अन्य सभी द्वारा दिए गए उदाहरणों के आधार पर मेरा समाधान है। चूंकि अधिकांश लोग नकारात्मक संख्याओं को संभालने के लिए इसकी तलाश कर रहे थे, इसलिए यह समाधान बस यही करता है, बिना किसी विशेष कार्य के उपयोग के बिना, अर्थात पेट, और पसंद।

मॉडुलस से बचने और इसके बजाय विभाजन का उपयोग करके, नकारात्मक संख्या एक प्राकृतिक परिणाम है, हालांकि यह नीचे गोल है। राउंड डाउन डाउन संस्करण की गणना की जाती है, तो यह राउंड अप करने के लिए आवश्यक गणित करता है, या तो नकारात्मक या सकारात्मक दिशा में।

यह भी ध्यान दें कि कुछ भी गणना करने के लिए किसी विशेष फ़ंक्शन का उपयोग नहीं किया जाता है, इसलिए वहां एक छोटी गति को बढ़ावा मिलता है।

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अतिप्रवाह।
चुक्स - मोनिका

1

मुझे लगता है कि इससे आपको मदद मिलनी चाहिए। मैंने सी में नीचे कार्यक्रम लिखा है।

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

क्या आपने अपने विचार को प्रस्तुत करने की जाँच की है? यह संदिग्ध जवाब देता है
योदव

यह मान्य कोड भी नहीं है।
user13783520
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.