Jak zaokrąglić wynik dzielenia liczb całkowitych?

Myślę w szczególności o tym, jak wyświetlać kontrolki paginacji, używając języka takiego jak C # lub Java.

Jeśli mam x elementy, które chcę wyświetlić w kawałkach y na stronę, ile stron będzie potrzebnych?

 280
Author: Joris Schellekens, 2008-08-20

15 answers

Znalazłem eleganckie rozwiązanie:

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

Źródło: Konwersja Liczb, Roland Backhouse, 2001

 413
Author: Ian Nelson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-20 13:42:08

Konwersja na zmiennoprzecinkową i wsteczną wydaje się ogromną stratą czasu na poziomie procesora.

Rozwiązanie Iana Nelsona:

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

Można uprościć do:

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

AFAICS, to nie ma błędu przepełnienia, który Brandon DuRette wskazał, a ponieważ używa go tylko raz, nie musisz przechowywać recordspepage specjalnie, jeśli pochodzi z drogiej funkcji, aby pobrać wartość z pliku konfiguracyjnego lub czegoś takiego.

Tzn. może to być nieefektywne, jeśli config.fetch_value użyło wyszukiwania bazy danych lub czegoś takiego:

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

To tworzy zmienną, której tak naprawdę nie potrzebujesz, która prawdopodobnie ma (drobne) implikacje pamięci i jest po prostu zbyt wiele wpisywania:

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

To wszystko jest jedną linią i pobiera dane tylko raz:

int pageCount = (records - 1) / config.fetch_value('records per page') + 1;
 168
Author: rjmunro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-02 13:26:00

To powinno dać ci to, czego chcesz. Na pewno będziesz chciał x elementów podzielonych przez Y elementów na stronie, problem jest, gdy pojawiają się nierówne liczby, więc jeśli istnieje częściowa strona, chcemy również dodać jedną stronę.

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);
 59
Author: Nick Berardi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-20 13:39:51

W C# rozwiązaniem jest rzut wartości do dwójki (jak Math.Sufit zajmuje podwójne):

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

W Javie powinieneś zrobić to samo z matematyką.ceil ().

 58
Author: Huppie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-29 21:24:08

Rozwiązanie integer math dostarczone przez Iana jest ładne, ale cierpi na błąd integer overflow. Przy założeniu, że wszystkie zmienne są int, rozwiązanie można przepisać tak, aby używać long matematyki i uniknąć błędu:

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

Jeśli records jest long, błąd pozostaje. Rozwiązanie modułu nie ma błędu.

 16
Author: Brandon DuRette,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-31 06:51:57

Wariant odpowiedzi Nicka Berardiego, który unika gałęzi:

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

Uwaga: (-r >> (Integer.SIZE - 1)) składa się z bitu znaku r, Powtórzonego 32 razy (dzięki rozszerzeniu znaku operatora >>.) Wartość ta wynosi 0, Jeśli r jest równa zero lub ujemna, -1, jeśli r jest dodatnia. Zatem odejmowanie od q powoduje dodanie 1 if records % recordsPerPage > 0.

 6
Author: finnw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:45

Dla rekordów = = 0, rozwiązanie rjmunro daje 1. Poprawnym rozwiązaniem jest 0. To powiedziawszy, jeśli wiesz, że rekordy > 0 (i jestem pewien, że wszyscy założyliśmy recordspepage > 0), To rozwiązanie rjmunro daje prawidłowe wyniki i nie ma żadnych problemów z przepełnieniem.

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

Wszystkie całkowe rozwiązania matematyczne będą bardziej wydajne niż dowolne z rozwiązań zmiennoprzecinkowych.

 4
Author: Mike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-11 10:41:28

In need of an extension method:

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

Brak tu sprawdzeń (przepełnienie, DivideByZero, itp.), możesz dodać, jeśli chcesz. Nawiasem mówiąc, dla tych, którzy martwią się o wywołanie metody, proste funkcje takie jak ta mogą być i tak wbudowane przez kompilator, więc nie sądzę, że o to chodzi. Zdrowie.

P. S. może się okazać przydatne, aby być tego świadomym (dostaje resztę):

    int remainder; 
    int result = Math.DivRem(dividend, divisor, out remainder);
 3
Author: Nicholas Petersen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-15 19:52:17

Inną alternatywą jest użycie funkcji mod () (lub'%'). Jeśli istnieje niezerowa reszta, zwiększ liczbę całkowitą wyniku dzielenia.

 2
Author: Jarod Elliott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-20 13:30:43

Wykonuję następujące czynności, obsługuję wszelkie przelewy:

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

I użyj tego rozszerzenia, jeśli jest 0 wyników:

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

Również dla bieżącego numeru strony (nie był pytany, ale może być przydatny):

var currentPage = (int) Math.Ceiling(recordsperpage/(double) recordsperpage) + 1;
 1
Author: Sam Jones,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-04 09:36:58

Alternatywa dla usunięcia rozgałęzienia w testowaniu dla zera:

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

Nie wiem czy to zadziała w C#, powinno działać w C / C++.

 0
Author: flux,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-13 03:26:08

Metoda ogólna, której wynik można iterować może być interesująca:

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;
}
 -1
Author: Jeremy Hadfied,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-28 14:09:15

Miałem podobną potrzebę, w której musiałem przekonwertować minuty na godziny i minuty. Użyłem:

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
Author: Richard Parsons,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-19 17:06:05

Poniższe powinny robić zaokrąglenia lepiej niż powyższe rozwiązania, ale kosztem wydajności (ze względu na obliczanie zmiennoprzecinkowe 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;
}
 -2
Author: Jim Watson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-07 15:21:15

Będziesz chciał dokonać podziału zmiennoprzecinkowego, a następnie użyć funkcji sufit, aby zaokrąglić wartość do następnej liczby całkowitej.

 -4
Author: Kibbee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-20 13:29:57