पूर्णांक विभाजन के परिणाम को कैसे गोल किया जाए?


335

मैं विशेष रूप से सोच रहा हूँ कि कैसे C # या जावा जैसी भाषा का उपयोग करते समय पृष्ठ पर अंकुरण नियंत्रण प्रदर्शित करें।

यदि मेरे पास x आइटम हैं जो मैं प्रति पृष्ठ y के भाग में प्रदर्शित करना चाहता हूं , तो कितने पृष्ठों की आवश्यकता होगी?


1
क्या मैं कुछ भूल रहा हूँ? y / x + 1 बहुत अच्छा काम करता है (बशर्ते आप जानते हैं / ऑपरेटर हमेशा गोल हो जाता है)।
रिक्तित

51
@rikkit - यदि y और x बराबर हैं, तो y / x + 1 एक बहुत अधिक है।
इयान नेल्सन

1
किसी के लिए भी अभी यह पता लग रहा है, एक प्रश्न का यह उत्तर एक दोहरे प्रश्न से अनावश्यक रूपांतरण से बचता है और एक स्पष्ट विवरण प्रदान करने के अलावा अतिप्रवाह की चिंताओं से बचा जाता है।
ZX9

2
@IanNelson अधिक आम तौर पर अगर xविभाज्य है y, y/x + 1तो एक बहुत अधिक होगा।
ओहद श्नाइडर

1
@ ZX9 नहीं, यह अतिप्रवाह की चिंताओं से नहीं बचता है। यह बिल्कुल वैसा ही समाधान है जैसा कि इयान नेल्सन ने यहां पोस्ट किया है।
14:24 पर user247702

जवाबों:


478

एक सुंदर समाधान मिला:

int pageCount = (records + recordsPerPage - 1) / recordsPerPage;

स्रोत: नंबर रूपांतरण, रोलैंड बैकहाउस, 2001


12
-1 क्योंकि अतिप्रवाह बग के द्वारा कहा ब्रैंडन Durette
finnw

30
श्री स्पष्ट कहते हैं: याद रखना सुनिश्चित करें कि रिकॉर्डरेजेज शून्य नहीं है
एडम जेंट

7
अच्छा काम है, मुझे विश्वास नहीं हो रहा है कि C # में पूर्णांक छत नहीं है।
गोसुकीवि

2
हाँ, यहाँ मैं कई और अधिक जटिल तरीकों की कोशिश करने के बाद इस शानदार उत्तर के मध्य 2017 में ठोकर खा रहा हूँ।
Mifo

1
पाइथन जैसे एक उचित यूक्लिडियन-डिवीजन ऑपरेटर वाली भाषाओं के लिए, और भी सरल दृष्टिकोण होगा pageCount = -((-records) // recordsPerPage)
सुपरकैट

194

सीपीयू स्तर पर समय की भारी बर्बादी की तरह फ्लोटिंग पॉइंट और बैक में परिवर्तित होना।

इयान नेल्सन का समाधान:

int pageCount = (records + recordsPerPage - 1) / recordsPerPage;

सरल किया जा सकता है:

int pageCount = (records - 1) / recordsPerPage + 1;

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

यानी यह अक्षम हो सकता है, अगर config.fetch_value डेटाबेस लुकअप या कुछ का उपयोग करता है:

int pageCount = (records + config.fetch_value('records per page') - 1) / config.fetch_value('records per page');

यह एक ऐसा चर बनाता है जिसकी आपको वास्तव में आवश्यकता नहीं है, जिसमें संभवतः (मामूली) मेमोरी निहितार्थ है और बस बहुत अधिक टाइपिंग है:

int recordsPerPage = config.fetch_value('records per page')
int pageCount = (records + recordsPerPage - 1) / recordsPerPage;

यह सभी एक पंक्ति है, और केवल एक बार डेटा प्राप्त करता है:

int pageCount = (records - 1) / config.fetch_value('records per page') + 1;

5
+1, शून्य रिकॉर्ड का मुद्दा अभी भी 1 पेज लौटा रहा है वास्तव में आसान है, क्योंकि मैं अभी भी 1 पेज चाहता हूं, "कोई भी रिकॉर्ड आपके मानदंड से मेल नहीं खाता" के प्लेसहोल्डर / नकली पंक्ति को दिखाते हुए, किसी भी "0 पेज की गिनती" के मुद्दों से बचने में मदद करता है पृष्ठ पर अंक लगाना नियंत्रण जिसका आप उपयोग करते हैं।
टिमोथी वाल्टर्स

27
विदित हो कि दो समाधान एक ही पृष्ठ वापस नहीं लाते हैं। यह सरलीकृत संस्करण शून्य रिकॉर्ड के लिए 1 पेजकाउंट लौटाएगा, जबकि रोलैंड बैकहाउस संस्करण 0 पेजकाउंट देता है। यदि आप चाहें तो ठीक है, लेकिन C # / Java स्टाइल पूर्णांक विभाजन द्वारा किए जाने पर दो समीकरण समतुल्य नहीं होते हैं।
इयान नेल्सन

10
नेल्सन समाधान (जैसे मैंने पहली बार किया था!) ​​से सिम्फिकेशन में बदलते समय, इसे स्कैन करने वाले लोगों के लिए स्पष्टता और अनुपलब्ध बॉडमास के लिए छोटा सा संपादन ... ब्रैकेट के साथ सरलीकरण है ... int pageCount = (रिकॉर्ड्स - 1) या रिकॉर्डपेयरेज! + 1;
हेजवुड को दिया

1
आपको कोष्ठक को सरलीकृत संस्करण में जोड़ना चाहिए ताकि यह परिचालन के विशिष्ट क्रम पर निर्भर न हो। यानी, ((रिकॉर्ड्स - 1) / रिकॉर्ड्सपेज) + 1.
मार्टिन

1
@ नहीं, यह उत्तर हमेशा नहीं लौटता है। यदि आपके रिकॉर्ड्सपेज "1" है और यह 1 रिकॉर्ड है तो यह 0 वापस आ सकता है -1 / 1 + 1 = 0:। हालांकि यह एक सामान्य सामान्य घटना नहीं है, लेकिन यदि आप उपयोगकर्ताओं को पृष्ठ आकार समायोजित करने की अनुमति दे रहे हैं, तो इसे ध्यान में रखना महत्वपूर्ण है। इसलिए या तो उपयोगकर्ताओं को पृष्ठ का आकार 1 करने की अनुमति न दें, पृष्ठ आकार की जांच करें, या दोनों (संभवतः अप्रत्याशित व्यवहार से बचने के लिए बेहतर)।
माइकल

81

C # के लिए समाधान एक डबल करने के लिए मानों (जैसे Math.Ceiling एक डबल लेता है) के लिए है:

int nPages = (int)Math.Ceiling((double)nItems / (double)nItemsPerPage);

जावा में आपको Math.ceil () के साथ भी ऐसा ही करना चाहिए।


4
जब ओ # सी के लिए स्पष्ट रूप से पूछता है तो यह जवाब इतना नीचे क्यों है!
felickz

2
इनपुट प्रकारों के आधार पर, आपको आउटपुट देने की आवश्यकता है intक्योंकि या , Math.Ceilingरिटर्न doubleया decimal
DanM7

15
क्योंकि यह बेहद अक्षम है
ज़ार शारदान

6
यह अक्षम हो सकता है लेकिन इसे समझना बेहद आसान है। पृष्ठ गणना की गणना आमतौर पर अनुरोध के अनुसार एक बार की जाती है, किसी भी प्रदर्शन हानि औसत दर्जे का नहीं होगा।
जारेड क्लेल्स

1
इसके बमुश्किल अधिक पठनीय है "(लाभांश + (भाजक - 1)) / भाजक;" यह भी धीमा है और गणित पुस्तकालय की आवश्यकता है।
रोल

68

यह आपको वह देना चाहिए जो आप चाहते हैं। आप निश्चित रूप से x आइटम को प्रति पृष्ठ y आइटम से विभाजित करना चाहते हैं, समस्या तब होती है जब असमान संख्याएं आती हैं, इसलिए यदि कोई आंशिक पृष्ठ है तो हम एक पृष्ठ भी जोड़ना चाहते हैं।

int x = number_of_items;
int y = items_per_page;

// with out library
int pages = x/y + (x % y > 0 ? 1 : 0)

// with library
int pages = (int)Math.Ceiling((double)x / (double)y);

5
x / y + !! (x% y) सी जैसी भाषाओं के लिए शाखा से बचा जाता है। ऑड्स अच्छे हैं, हालांकि, आपका कंपाइलर वैसे भी कर रहा है।
Rhys Ulerich

2
+1 ऊपर दिए गए उत्तरों की तरह ओवरफ्लो नहीं करने के लिए ... हालांकि केवल मैथ.सेलिंग के लिए डबल्स में कनवर्ट करना और फिर वापस परफॉर्मेंस सेंसिटिव कोड में एक बुरा विचार है।
कोगव्हील

3
@RhysUlerich जो c # में काम नहीं करता है (सीधे इंट को बूल में परिवर्तित नहीं कर सकता है)। rjmunro का समाधान मुझे लगता है कि शाखा से बचने का एकमात्र तरीका है।
1

18

पूर्णांक गणित समाधान जो इयान ने प्रदान किया है वह अच्छा है, लेकिन एक पूर्णांक अतिप्रवाह बग से ग्रस्त है। चर सभी को मानते हुए int, longगणित का उपयोग करने और बग से बचने के लिए समाधान को फिर से लिखा जा सकता है :

int pageCount = (-1L + records + recordsPerPage) / recordsPerPage;

यदि recordsए है long, तो बग बना रहता है। मापांक समाधान में बग नहीं है।


4
मुझे नहीं लगता कि आप वास्तव में प्रस्तुत किए गए परिदृश्य में इस बग को हिट करने जा रहे हैं। 2 ^ 31 रिकॉर्ड पेज के माध्यम से होने के लिए काफी है।
rjmunro


@ फ़िन्विक: AFAICS, उस पृष्ठ पर वास्तविक दुनिया का उदाहरण नहीं है, बस किसी और की रिपोर्ट को एक सैद्धांतिक परिदृश्य में बग ढूंढ रहा है।
rjmunro

5
हां, बग को इंगित करने में मुझे पांडित्य हो रहा था। कई कीड़े बिना किसी समस्या के हमेशा के लिए मौजूद हो सकते हैं। JDK के बाइनरीसर्च के कार्यान्वयन में उसी फॉर्म का एक बग लगभग नौ वर्षों से मौजूद था, इससे पहले कि कोई इसकी रिपोर्ट करे ( googleresearch.blogspot.com/2006/06/… )। मुझे लगता है कि सवाल यह है कि इस बग का सामना करने की कितनी संभावना है, फिर भी इसे ठीक क्यों नहीं किया जाए?
ब्रैंडन ड्यूरेट

4
इसके अलावा, यह ध्यान दिया जाना चाहिए कि यह केवल उन तत्वों की संख्या नहीं है जो उस मामले को पृष्ठांकित करते हैं, यह पृष्ठ आकार भी है। इसलिए, यदि आप एक पुस्तकालय का निर्माण कर रहे हैं और कोई व्यक्ति पृष्ठ के आकार के रूप में 2 ^ 31-1 (Integer.MAX_VALUE) पास करके पृष्ठ का चयन नहीं करता है, तो बग चालू हो जाता है।
ब्रैंडन ड्यूरेट

7

निक बेर्डी के उत्तर का एक प्रकार जो एक शाखा से बचा जाता है:

int q = records / recordsPerPage, r = records % recordsPerPage;
int pageCount = q - (-r >> (Integer.SIZE - 1));

नोट: (-r >> (Integer.SIZE - 1))साइन बिट के होते हैं r, दोहराया 32 बार ( >>ऑपरेटर के हस्ताक्षर विस्तार के लिए धन्यवाद ।) यह 0 का मूल्यांकन करता है यदि rशून्य या नकारात्मक है, -1 rसकारात्मक है। तो इससे घटाकर q1 जोड़ने का प्रभाव पड़ता है अगर records % recordsPerPage > 0


4

रिकॉर्ड्स के लिए == 0, rjmunro का सॉल्यूशन देता है। 1. सही सॉल्यूशन है 0. यह कहा गया है, अगर आपको पता है कि रेकॉर्ड्स 0 (और मुझे यकीन है कि हम सभी रेकॉर्डपेयर> 0) मान चुके हैं, तो rjmunro सॉल्यूशन सही परिणाम देता है। अतिप्रवाह के मुद्दों में से कोई भी नहीं है।

int pageCount = 0;
if (records > 0)
{
    pageCount = (((records - 1) / recordsPerPage) + 1);
}
// no else required

सभी पूर्णांक गणित समाधान किसी भी फ्लोटिंग पॉइंट समाधान की तुलना में अधिक कुशल होने वाले हैं।


इस पद्धति के प्रदर्शन में अड़चन होने की संभावना नहीं है। और अगर यह है, तो आपको शाखा की लागत पर भी विचार करना चाहिए।
फिनीव

4

एक विस्तार विधि की जरूरत में:

    public static int DivideUp(this int dividend, int divisor)
    {
        return (dividend + (divisor - 1)) / divisor;
    }

यहां कोई चेक (ओवरफ्लो, DivideByZeroआदि), यदि आप चाहें तो जोड़ने के लिए स्वतंत्र महसूस करें। वैसे, विधि आह्वान ओवरहेड के बारे में चिंतित लोगों के लिए, इस तरह के सरल कार्यों को संकलक वैसे भी इनलाइन किया जा सकता है, इसलिए मुझे नहीं लगता कि जहां संबंध होना चाहिए। चीयर्स।

PS आपको इसके बारे में जानकारी होना उपयोगी हो सकता है (यह शेष मिलता है):

    int remainder; 
    int result = Math.DivRem(dividend, divisor, out remainder);

1
यह गलत है। उदाहरण के लिए: DivideUp(4, -2)रिटर्न 0 (-2 होना चाहिए)। यह केवल गैर-नकारात्मक पूर्णांक के लिए सही है जो उत्तर से या फ़ंक्शन के इंटरफ़ेस से स्पष्ट नहीं है।
थाश

6
Thash, आप कुछ उपयोगी क्यों नहीं करते जैसे थोड़ा अतिरिक्त चेक जोड़ते हैं, यदि संख्या नकारात्मक है, तो मेरे जवाब को वोट करने के बजाय, और गलत तरीके से कंबल बयान कर रहा है: "यह गलत है," जब वास्तव में यह सिर्फ एक बढ़त है मामला। मैंने पहले ही स्पष्ट कर दिया है कि आपको पहले अन्य जाँचें करनी चाहिए: "यहाँ कोई जाँच नहीं (अतिप्रवाह, डिवाइडबीजेरो, इत्यादि), यदि आप चाहें तो जोड़ने के लिए स्वतंत्र महसूस करें ।"
निकोलस पीटरसन

1
उल्लेख किया गया प्रश्न "मैं विशेष रूप से सोच रहा हूं कि कैसे पृष्ठ पर अंकुरण नियंत्रण प्रदर्शित किया जाए" तो नकारात्मक संख्या किसी भी सीमा से बाहर हो जाती। फिर से, बस कुछ उपयोगी है और यदि आप चाहते हैं कि एक अतिरिक्त जाँच का सुझाव है, यह एक टीम प्रयास आदमी है।
निकोलस पीटरसन

मेरे अशिष्ट होने का मतलब यह नहीं था कि अगर आप इसे इस तरह से लेते हैं तो मुझे खेद है। सवाल था "पूर्णांक विभाजन के परिणाम को कैसे गोल किया जाए"। लेखक ने पृष्ठांकन का उल्लेख किया है लेकिन अन्य लोगों की अलग-अलग आवश्यकताएं हो सकती हैं। मुझे लगता है कि यह बेहतर होगा यदि आपका फ़ंक्शन किसी भी तरह से प्रतिबिंबित करता है कि यह नकारात्मक पूर्णांक के लिए काम नहीं करता है क्योंकि यह इंटरफ़ेस से स्पष्ट नहीं है (उदाहरण के लिए एक अलग नाम या तर्क प्रकार)। नकारात्मक पूर्णांक के साथ काम करने के लिए, आप उदाहरण के लिए लाभांश और भाजक का पूर्ण मूल्य ले सकते हैं और परिणाम को उसके संकेत से गुणा कर सकते हैं।
थश

2

एक अन्य विकल्प मॉड () फ़ंक्शन (या '%') का उपयोग करना है। यदि कोई गैर-शून्य शेष है तो विभाजन का पूर्णांक परिणाम बढ़ाएँ।


1

मैं निम्नलिखित करता हूं, किसी भी ओवरफ्लो को संभालता हूं:

var totalPages = totalResults.IsDivisble(recordsperpage) ? totalResults/(recordsperpage) : totalResults/(recordsperpage) + 1;

और 0 के परिणाम होने पर इस एक्सटेंशन का उपयोग करें:

public static bool IsDivisble(this int x, int n)
{
           return (x%n) == 0;
}

वर्तमान पृष्ठ संख्या के लिए भी (पूछा नहीं गया, लेकिन उपयोगी हो सकता है):

var currentPage = (int) Math.Ceiling(recordsperpage/(double) recordsperpage) + 1;

0

शून्य के लिए परीक्षण में शाखाओं को हटाने के लिए वैकल्पिक:

int pageCount = (records + recordsPerPage - 1) / recordsPerPage * (records != 0);

सुनिश्चित नहीं है कि यह C # में काम करेगा, C / C ++ में करना चाहिए।


-1

एक सामान्य विधि, जिसका परिणाम आप पर ब्याज कर सकते हैं:

public static Object[][] chunk(Object[] src, int chunkSize) {

    int overflow = src.length%chunkSize;
    int numChunks = (src.length/chunkSize) + (overflow>0?1:0);
    Object[][] dest = new Object[numChunks][];      
    for (int i=0; i<numChunks; i++) {
        dest[i] = new Object[ (i<numChunks-1 || overflow==0) ? chunkSize : overflow ];
        System.arraycopy(src, i*chunkSize, dest[i], 0, dest[i].length); 
    }
    return dest;
}

अमरूद में एक समान विधि ( Lists.partition(List, int)) है और विडंबना यह size()है कि परिणामस्वरूप List(जैसा कि r09) ब्रैंडन ड्यूरेट के उत्तर में उल्लिखित अतिप्रवाह बग से ग्रस्त है ।
फिनीव

-2

मुझे इसी तरह की आवश्यकता थी जहां मुझे मिनटों को घंटों और मिनटों में बदलने की आवश्यकता थी। मैंने जो प्रयोग किया वह था:

int hrs = 0; int mins = 0;

float tm = totalmins;

if ( tm > 60 ) ( hrs = (int) (tm / 60);

mins = (int) (tm - (hrs * 60));

System.out.println("Total time in Hours & Minutes = " + hrs + ":" + mins);

-2

उपरोक्त समाधानों की तुलना में निम्नलिखित को बेहतर तरीके से किया जाना चाहिए, लेकिन प्रदर्शन की कीमत पर (0.5 * rctDenominator की फ्लोटिंग पॉइंट गणना के कारण):

uint64_t integerDivide( const uint64_t& rctNumerator, const uint64_t& rctDenominator )
{
  // Ensure .5 upwards is rounded up (otherwise integer division just truncates - ie gives no remainder)
  return (rctDenominator == 0) ? 0 : (rctNumerator + (int)(0.5*rctDenominator)) / rctDenominator;
}

-4

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

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