정수 나눗셈 결과를 어떻게 반올림합니까?
특히 C#이나 Java 등의 언어를 사용할 때 페이지화 컨트롤을 표시하는 방법을 생각하고 있습니다.
1페이지당 y단위로 표시하고 싶은 아이템이 x개 있으면 몇페이지가 필요합니까?
우아한 솔루션 발견:
int pageCount = (records + recordsPerPage - 1) / recordsPerPage;
출처 : Roland Backhouse, 2001, 번호 변환
부동소수점 및 역방향으로 변환하는 것은 CPU 레벨에서 엄청난 시간 낭비라고 생각됩니다.
Ian Nelson의 솔루션:
int pageCount = (records + recordsPerPage - 1) / recordsPerPage;
다음과 같이 단순화할 수 있습니다.
int pageCount = (records - 1) / recordsPerPage + 1;
AFAICS는 Brandon DuRette가 지적한 오버플로 버그를 가지고 있지 않습니다.또한 1회만 사용하기 때문에 Config 파일에서 값을 취득하기 위해 고가의 함수에서 recordsPerPage를 저장할 필요가 없습니다.
즉, 구성 시 비효율적일 수 있습니다.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;
C#의 경우 값을 2배(Math)로 캐스팅하는 것이 해결책입니다.천장에 두 배가 필요):
int nPages = (int)Math.Ceiling((double)nItems / (double)nItemsPerPage);
자바에서는 Math.ceil()에서도 같은 작업을 수행해야 합니다.
이게 네가 원하는 걸 줄 거야1페이지당 x개의 아이템을 y개의 아이템으로 나누면 좋겠다고 생각합니다만, 문제가 되는 것은, 일부의 페이지가 있으면, 1페이지를 추가하고 싶다고 생각하고 있습니다.
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이 제공한 정수 산술 해법은 좋지만 정수 오버플로 버그가 있습니다.변수가 모두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회 반복합니다.>>
오퍼레이터).이 값은 0으로 평가됩니다.r
0 또는 음수입니다. -1의 경우r
양성입니다.그래서 뺄셈을 하면q
1을 더하는 효과가 있습니다.records % recordsPerPage > 0
.
확장 방법이 필요한 경우:
public static int DivideUp(this int dividend, int divisor)
{
return (dividend + (divisor - 1)) / divisor;
}
여기 체크 없음(오버플로우,DivideByZero
, 등)를 추가해 주세요.덧붙여서 메서드 호출 오버헤드가 걱정되는 분들을 위해 컴파일러에 이러한 단순한 함수가 삽입되어 있을지도 모르기 때문에 그 부분은 신경 쓸 필요가 없다고 생각합니다.건배.
P.S. 이 점에 유의하는 것이 도움이 될 수 있습니다(나머지는 취득).
int remainder;
int result = Math.DivRem(dividend, divisor, out remainder);
C#의 정수 나눗셈 결과를 정리하는 방법
최대 10만 회까지 루프해야 하기 때문에 C#에서 이 작업을 수행하는 가장 좋은 방법이 무엇인지 알고 싶었습니다.다른 사람이 수학을 사용하여 게시한 해답은 정답 순위가 높지만 테스트에서는 느리다는 것을 알게 되었습니다.Jarod Elliott는 mod가 무언가를 생산하는지 확인하는 더 나은 전략을 제안했다.
int result = (int1 / int2);
if (int1 % int2 != 0) { result++; }
이거 100만 번 돌렸는데8ms 걸렸어요다음은 산술을 사용한 코드입니다.
int result = (int)Math.Ceiling((double)int1 / (double)int2);
테스트에서 14ms로 꽤 오래 걸렸어요
레코드 == 0의 경우 rjmunro의 솔루션은 1을 제공합니다.정답은 0입니다.즉, records > 0(및 모두 records Per Page > 0을 상정하고 있다고 확신)을 알고 있는 경우 rjmunro 솔루션은 올바른 결과를 얻을 수 있으며 오버플로우 문제는 발생하지 않습니다.
int pageCount = 0;
if (records > 0)
{
pageCount = (((records - 1) / recordsPerPage) + 1);
}
// no else required
모든 정수 수학 해법은 부동 소수점 해법보다 효율적입니다.
또 다른 방법은 mod() 함수(또는 '%')를 사용하는 것입니다.0이 아닌 나머지가 있는 경우 나눗셈의 정수 결과를 증가시킵니다.
다음을 수행하여 오버플로우를 처리합니다.
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;
사용할 수 있습니다.
(int)Math.Ceiling(((decimal)model.RecordCount )/ ((decimal)4));
제로 테스트에서 분기를 제거하는 대체 방법:
int pageCount = (records + recordsPerPage - 1) / recordsPerPage * (records != 0);
이것이 C#에서 동작할지 어떨지, C/C++에서 동작할지는 확실하지 않습니다.
결과를 반복할 수 있는 일반적인 방법이 필요할 수 있습니다.
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;
}
마찬가지로 회의록을 시간 및 분으로 변환해야 했습니다.제가 사용한 건
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);
다음은 위의 솔루션보다 반올림을 더 잘하지만 (부동소수점 계산 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;
}
부동 소수점 나눗셈을 수행한 다음 상한 함수를 사용하여 값을 다음 정수로 반올림할 수 있습니다.
언급URL : https://stackoverflow.com/questions/17944/how-to-round-up-the-result-of-integer-division
'programing' 카테고리의 다른 글
IntelliJ IDEA를 사용하여 Java 코드 행을 계산하는 방법 (0) | 2022.08.10 |
---|---|
ERR_로 인해 리플릿 JS의 마커가 올바르게 로드되지 않습니다.INVALID_URL 오류 (0) | 2022.08.10 |
VueX: 외부 키의 데이터를 로드하는 방법(마이크로 서비스 아키텍처) (0) | 2022.08.10 |
VUEX: 상태 객체 전체에 영향을 줄 수 없는 이유는 무엇입니까? (0) | 2022.08.10 |
포인터 선언에 별표 배치 (0) | 2022.08.10 |