Вопрос:

Как округлить результат целочисленного деления?

c# java math

168595 просмотра

16 ответа

35405 Репутация автора

В частности, я думаю о том, как отображать элементы управления нумерацией страниц при использовании таких языков, как C # или Java.

Если у меня есть x элементов, которые я хочу отображать кусками y на странице, сколько страниц потребуется?

Автор: Ian Nelson Источник Размещён: 20.08.2008 01:27

Ответы (16)


-4 плюса

51640 Репутация автора

Вы захотите сделать деление с плавающей запятой, а затем использовать функцию потолка, чтобы округлить значение до следующего целого числа.

Автор: Kibbee Размещён: 20.08.2008 01:29

2 плюса

12857 Репутация автора

Другой альтернативой является использование функции mod () (или «%»). Если есть ненулевой остаток, то увеличиваем целочисленный результат деления.

Автор: Jarod Elliott Размещён: 20.08.2008 01:30

62 плюса

45582 Репутация автора

Это должно дать вам то, что вы хотите. Вы определенно захотите, чтобы 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);
Автор: Nick Berardi Размещён: 20.08.2008 01:31

61 плюса

9120 Репутация автора

Для C # решение состоит в приведении значений к двойному (поскольку Math.Ceiling принимает двойное):

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

В Java вы должны сделать то же самое с Math.ceil ().

Автор: Huppie Размещён: 20.08.2008 01:33

422 плюса

35405 Репутация автора

Решение

Нашли элегантное решение:

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

Источник: Преобразование чисел, Роланд Бэкхаус, 2001

Автор: Ian Nelson Размещён: 20.08.2008 01:42

17 плюса

3780 Репутация автора

Целочисленное математическое решение, которое предоставил Ян, хорошо, но страдает от ошибки целочисленного переполнения. Предполагая, что все переменные int, решение может быть переписано для использования longматематики и избежания ошибки:

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

Если recordsесть long, ошибка остается. В модульном решении нет ошибки.

Автор: Brandon DuRette Размещён: 18.09.2008 09:01

173 плюса

18499 Репутация автора

Преобразование в плавающую точку и обратно кажется огромной тратой времени на уровне процессора.

Решение Яна Нельсона:

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

Можно упростить до:

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

AFAICS, в нем нет ошибки переполнения, на которую указал Брэндон Дуретт, и поскольку он использует ее только один раз, вам не нужно специально хранить recordsPerPage, если она исходит из дорогой функции для извлечения значения из файла конфигурации или что-то.

Т.е. это может быть неэффективно, если 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;
Автор: rjmunro Размещён: 02.02.2009 01:26

4 плюса

1021 Репутация автора

Для записей == 0 решение rjmunro дает 1. Правильное решение равно 0. Тем не менее, если вы знаете, что записи> 0 (и я уверен, что мы все предположили recordsPerPage> 0), то решение rjmunro дает правильные результаты и не имеет никаких проблем переполнения.

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

Все целочисленные математические решения будут более эффективными, чем любое из решений с плавающей запятой.

Автор: Mike Размещён: 11.02.2009 10:18

0 плюса

142 Репутация автора

Альтернатива для удаления ветвления при тестировании на ноль:

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

Не уверен, что это будет работать в C #, следует делать в C / C ++.

Автор: flux Размещён: 13.08.2010 03:26

-1 плюса

9 Репутация автора

Общий метод, чей результат вы можете перебрать, может представлять интерес:

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;
}
Автор: Jeremy Hadfied Размещён: 28.10.2010 02:09

7 плюса

38469 Репутация автора

Вариант ответа Ника Берарди, который избегает ответвления:

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

Примечание: (-r >> (Integer.SIZE - 1))состоит из знакового бита r, повторяемого 32 раза (благодаря расширению знака >>оператора.) Это значение rравно 0, если равно нулю или отрицательно, и -1, если rположительно. Таким образом, вычитание его из qимеет эффект добавления 1, если records % recordsPerPage > 0.

Автор: finnw Размещён: 04.05.2011 01:00

-2 плюса

1 Репутация автора

У меня была похожая потребность, когда мне нужно было конвертировать минуты в часы и минуты. То, что я использовал, было:

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);
Автор: Richard Parsons Размещён: 19.03.2012 01:47

-2 плюса

1 Репутация автора

Следующее должно делать округление лучше, чем вышеупомянутые решения, но за счет производительности (из-за вычисления с плавающей запятой 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;
}
Автор: Jim Watson Размещён: 07.02.2013 03:02

1 плюс

3234 Репутация автора

Я делаю следующее, обрабатывает любые переполнения:

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;
Автор: Sam Jones Размещён: 04.02.2014 09:36

3 плюса

4366 Репутация автора

При необходимости метода расширения:

    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);
Автор: Nicholas Petersen Размещён: 15.09.2016 07:52

0 плюса

408 Репутация автора

для C # используйте функцию Math.Ceiling:

var pageCount= Math.Ceiling((double)myList.Count() / recordsPerPage);

и Java используют функцию Math.Ceil:

int n = (int) Math.ceil((double)myList.size() / recordsPerPage));
Автор: Hamed Naeemaei Размещён: 28.02.2019 10:21
Вопросы из категории :
32x32