programing

정수 나눗셈 결과를 어떻게 반올림합니까?

procenter 2022. 8. 10. 22:11
반응형

정수 나눗셈 결과를 어떻게 반올림합니까?

특히 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으로 평가됩니다.r0 또는 음수입니다. -1의 경우r양성입니다.그래서 뺄셈을 하면q1을 더하는 효과가 있습니다.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

반응형