programing

C/C++에서 div 또는 ldiv를 사용하는 이유는 무엇입니까?

shortcode 2023. 9. 20. 20:55
반응형

C/C++에서 div 또는 ldiv를 사용하는 이유는 무엇입니까?

'/' 또는 '%' 대신 ldiv 또는 div를 사용하여 두 변수를 나누고 변조하는 특정한 이유가 있습니까?

예. C99 §7.20.6.2/2는 다음과 같이 말합니다.

div,ldiv,그리고.lldiv, numer / denom그리고.numer % denom

프로세서의 단일 DIV 명령을 통해 / 및 %의 결과를 파악할 수 있습니다.따라서 역사적으로 div()는 두 가지를 모두 얻을 수 있는 최적화된 방법을 제공하는 데 사용됩니다.

그러나 저는 새로운 컴파일러들이 / 및 % 연산을 단일 분할로 최적화할 수 있다는 것을 알게 되었습니다.예를 들어 Microsoft Visual C++에서 이러한 최적화를 본 적이 있습니다.이러한 경우 div()는 실제로 이점을 제공하지 않으며, 실제로 통화가 관련된 경우 속도가 더 느려질 수도 있습니다.

그것은 사용하는 것보다 더 빠를 입니다./그리고.%계수와 나머지를 동시에 계산하려는 경우에는 연산자를 사용합니다.

단답: 현대적인 환경에서는 그렇지 않습니다.

사람들은 왜 다음과 같은 혜택을 주는지 설명했습니다.div약하거나 심지어 존재하지 않는 것입니다.친구들은 좋은 관행을 해치는 유형의 커플링을 소개합니다(아래 단점 참조).

장점 : 아마도 없음

에게 를 걸면,div/그리고.%작업이 어셈블리 수준에서 한 번만 수행되도록 보장할 수 있습니다.

그러나 대부분의 현대적 맥락에서:

  1. CPU는 수학적 연산을 매우 잘 최적화하여 연산을 수 백만 번 수행하는 가장 안쪽 루프를 제외하고는 연산을 반복하여 수행할 경우 발생하는 모든 성능 히트가 다른 성능 히트보다 훨씬 적을 수 있습니다(다른 코드처럼 캐시 미스 등).=>=> 의div할 수 , .
  2. /그리고.%현대의 컴파일러는 계수를 가져오는 하나의 분할 명령어만 생성하고 나머지는 그로부터 생성함으로써 어쨌든 옳은 일을 합니다.=> 실익 없음div.

단점: 디브와 친구들은 당신의 코드를 특정 유형에 연결합니다.

(:int아니면long은 (즉, 가 항상 합니다(을 들어, int long 함), 을 사용하여 정적으로 알려져 있습니다.div위해서int그리고.ldiv오랫동안은 괜찮습니다.

을 하는 것이 하다는 을 금방 .div그리고.ldiv암호를 활자로 묶다int아니면long각각 다음과 같다.반대로./그리고.%코드를 깨끗하게 유지하면서 실제로 사용되는 유형이 무엇이든 자동으로 조정됩니다.

이는 특히 다음과 같은 두 가지 경우에 볼 수 있습니다.

  • 당신이 사용합니다typedef실제 활자를 추상화하다 보면 --divC에서도 서투릅니다!
  • 템플릿을 사용하여 실제 유형을 추상화합니다.div템플릿을 제거합니다.

아래 샘플은 '/' 및 '%'를 사용하는 코드가 깨끗하고 간단하며 int, long, long 등에 연결되지 않는 반면 코드를 사용하는 것을 보여줍니다.div친구들은 서툴러집니다.

Testing with int
my_math_func_div_WRONG  says 6
my_math_func_OVERKILL   says 6  // Works but overkill cast to long
my_math_func_GOOD   says 6      // No div no headache.

Testing with int in long type
my_math_func_div_WRONG  says 6
my_math_func_OVERKILL   says 6  // Works but overkill cast to long
my_math_func_GOOD   says 6      // No div no headache.

Testing with actual long
my_math_func_div_WRONG  says 70503280   // FAIL
my_math_func_OVERKILL   says 500000006
my_math_func_GOOD   says 500000006      // No div no headache.

소스 코드:

#include <iostream>

// '/' and '%' are smart about type.
// This code is simple and will work with int, long, longlong, char, whatever.
template<typename T>
T my_math_func_GOOD( T number )
{
    T quotient = number / 10;
    T remainder = number % 10;
    // do something
    return quotient + remainder;
}

// div and friends are not smart about type.
// How do you write code smart about type with them ?

// Plus adds dependency on C's stdlib.
#include <stdlib.h>
template<typename T>
T my_math_func_div_WRONG( T number )
{
    // This will always downcast to int. Defeats purpose of template.
    div_t result = div( number, 10 );
    T quotient = result.quot;
    T remainder = result.rem;
    // do something
    return quotient + remainder;
}

template<typename T>
T my_math_func_OVERKILL( T number )
{
    // This will always cast to long (up from int, OVERKILL, possibly down from long long, FAIL). Defeats purpose of template.
    ldiv_t result = ldiv( number, 10 );
    T quotient = result.quot;
    T remainder = result.rem;
    // do something
    return quotient + remainder;
}

template<typename T>
void my_math_func_test( T number )
{
    T n;
    n = my_math_func_div_WRONG( number );
    std::cout << "my_math_func_div_WRONG\tsays " << n << std::endl; // writes 6
    n = my_math_func_OVERKILL( number );
    std::cout << "my_math_func_OVERKILL\tsays " << n << std::endl; // writes 6
    n = my_math_func_GOOD( number );
    std::cout << "my_math_func_GOOD\tsays " << n << std::endl; // writes 6
}

// C99 allows absence of int argc, char **argv
int main()
{
    std::cout << std::endl << "Testing with int" << std::endl;
    my_math_func_test<int>( 42 );
    std::cout << std::endl << "Testing with int in long type" << std::endl;
    my_math_func_test<long>( 42 );
    std::cout << std::endl << "Testing with actual long" << std::endl;
    my_math_func_test<long>( 5000000042 );
    // std::cout << std::endl << "Testing with long long" << std::endl;
    // my_math_func_test<long long>( 50000000000000000042 );
}

좋아요, 나이가 더 많지만, 여기서 비틀거리기만 했어요.여기서 가장 중요한 차이점은 다음과 같습니다.div()의 결과가 정의됩니다.C 표준에는 계수를 반올림하는 방법이 나와 있지 않습니다.컴파일러는 CPU에 따라 다른 기계의 구현을 사용할 수 있어야 하기 때문입니다.-무한으로 반올림 - 0으로 반올림이라는 두 가지 다른 구현이 존재합니다.

그러나 div (),는 후자를 하도록 지정되어 있으므로 휴대가 가능합니다.

언급URL : https://stackoverflow.com/questions/4565272/why-use-div-or-ldiv-in-c-c

반응형