특히 C # 또는 Java와 같은 언어를 사용할 때 페이지 매김 컨트롤을 표시하는 방법을 생각하고 있습니다.
페이지 당 y 단위로 x 개의 항목을 표시하려는 경우 몇 개의 페이지가 필요합니까?
x
로 나누어 y
, y/x + 1
너무 높은 하나가 될 것입니다.
특히 C # 또는 Java와 같은 언어를 사용할 때 페이지 매김 컨트롤을 표시하는 방법을 생각하고 있습니다.
페이지 당 y 단위로 x 개의 항목을 표시하려는 경우 몇 개의 페이지가 필요합니까?
x
로 나누어 y
, y/x + 1
너무 높은 하나가 될 것입니다.
답변:
우아한 해결책을 찾았습니다.
int pageCount = (records + recordsPerPage - 1) / recordsPerPage;
pageCount = -((-records) // recordsPerPage)
.
부동 소수점으로 변환하면 CPU 수준에서 시간이 많이 낭비되는 것처럼 보입니다.
이안 넬슨의 솔루션 :
int pageCount = (records + recordsPerPage - 1) / recordsPerPage;
다음과 같이 단순화 할 수 있습니다.
int pageCount = (records - 1) / recordsPerPage + 1;
AFAICS, Brandon DuRette가 지적한 오버플로 버그는 없으며, 한 번만 사용하기 때문에 구성 파일에서 값을 가져 오기 위해 값 비싼 함수에서 오는 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;
-1 / 1 + 1 = 0
. 이는 일반적인 현상은 아니지만 사용자가 페이지 크기를 조정할 수있게하려면 명심해야합니다. 따라서 사용자가 페이지 크기를 1로 허용하지 않거나 페이지 크기를 확인하거나 두 가지 모두를 수행 할 수 있습니다 (예기치 않은 동작을 피하는 것이 좋습니다).
C #의 경우 솔루션은 값을 두 배로 캐스트하는 것입니다 (Math.Ceiling은 두 배가 됨).
int nPages = (int)Math.Ceiling((double)nItems / (double)nItemsPerPage);
Java에서는 Math.ceil ()과 동일하게 수행해야합니다.
int
있기 때문에 Math.Ceiling
리턴 double
또는 decimal
입력 유형에 따라.
이것은 당신이 원하는 것을 줄 것입니다. 페이지 당 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);
Ian이 제공 한 정수 수학 솔루션은 훌륭하지만 정수 오버플로 버그가 발생합니다. 변수가 all이라고 가정하면 수학 int
을 사용 long
하고 버그를 피하기 위해 솔루션을 다시 작성할 수 있습니다 .
int pageCount = (-1L + records + recordsPerPage) / recordsPerPage;
경우 records
인 long
, 버그 남아 있습니다. 모듈러스 솔루션에는 버그가 없습니다.
브랜치를 피하는 Nick Berardi의 답변 변형 :
int q = records / recordsPerPage, r = records % recordsPerPage;
int pageCount = q - (-r >> (Integer.SIZE - 1));
참고 : (-r >> (Integer.SIZE - 1))
부호 비트는 r
32 번 반복됩니다 ( >>
연산자 의 부호 확장 덕분에 ). r
이 값은 0이거나 음수이면 0으로, 양수이면 -1 r
로 평가됩니다. 따라서 그것을 빼면 q
1 if를 추가하는 효과가 records % recordsPerPage > 0
있습니다.
레코드 == 0의 경우, rjmunro의 솔루션은 1을 제공합니다. 올바른 솔루션은 0입니다. 즉, 레코드가 0보다 크다는 것을 알고 있다면 (그리고 나는 우리가 모두 레코드 PerPage> 0이라고 가정한다고 확신한다면) rjmunro 솔루션은 정확한 결과를 제공합니다. 오버플로 문제가 없습니다.
int pageCount = 0;
if (records > 0)
{
pageCount = (((records - 1) / recordsPerPage) + 1);
}
// no else required
모든 정수 수학 솔루션은 모든 부동 소수점 솔루션 보다 효율적 입니다.
확장 방법이 필요한 경우 :
public static int DivideUp(this int dividend, int divisor)
{
return (dividend + (divisor - 1)) / divisor;
}
여기에 수표 (오버플로 DivideByZero
등)가 없으며 원하는 경우 자유롭게 추가하십시오. 그건 그렇고, 메소드 호출 오버 헤드가 걱정되는 사람들에게는 이와 같은 간단한 함수가 어쨌든 컴파일러에 의해 인라인 될 수 있으므로 걱정할 부분은 없다고 생각합니다. 건배.
추신 : 당신도 이것을 알고 있으면 유용 할 것입니다 (나머지는 얻습니다).
int remainder;
int result = Math.DivRem(dividend, divisor, out remainder);
DivideUp(4, -2)
0을 반환합니다 (-2 여야 함). 대답이나 함수 인터페이스에서 명확하지 않은 음이 아닌 정수에만 정확합니다 .
다음을 수행하고 오버플로를 처리합니다.
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;
결과를 반복 할 수있는 일반적인 방법은 다음과 같습니다.
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
) Brandon DuRette의 답변 에서 언급 된 오버플로 버그로 인해 어려움을 겪고 있습니다 .
다음은 위의 솔루션보다 반올림해야하지만 성능을 희생해야합니다 (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;
}