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
/
그리고.%
작업이 어셈블리 수준에서 한 번만 수행되도록 보장할 수 있습니다.
그러나 대부분의 현대적 맥락에서:
- CPU는 수학적 연산을 매우 잘 최적화하여 연산을 수 백만 번 수행하는 가장 안쪽 루프를 제외하고는 연산을 반복하여 수행할 경우 발생하는 모든 성능 히트가 다른 성능 히트보다 훨씬 적을 수 있습니다(다른 코드처럼 캐시 미스 등).=>=> 의
div
할 수 , . /
그리고.%
현대의 컴파일러는 계수를 가져오는 하나의 분할 명령어만 생성하고 나머지는 그로부터 생성함으로써 어쨌든 옳은 일을 합니다.=> 실익 없음div
.
단점: 디브와 친구들은 당신의 코드를 특정 유형에 연결합니다.
(:int
아니면long
은 (즉, 가 항상 합니다(을 들어, int long 함), 을 사용하여 정적으로 알려져 있습니다.div
위해서int
그리고.ldiv
오랫동안은 괜찮습니다.
을 하는 것이 하다는 을 금방 .div
그리고.ldiv
암호를 활자로 묶다int
아니면long
각각 다음과 같다.반대로./
그리고.%
코드를 깨끗하게 유지하면서 실제로 사용되는 유형이 무엇이든 자동으로 조정됩니다.
이는 특히 다음과 같은 두 가지 경우에 볼 수 있습니다.
- 당신이 사용합니다
typedef
실제 활자를 추상화하다 보면 --div
C에서도 서투릅니다! - 템플릿을 사용하여 실제 유형을 추상화합니다.
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
'programing' 카테고리의 다른 글
현재 선택한 항목을 보존하면서 HTML 선택 옵션을 값별로 정렬하는 가장 효율적인 방법은 무엇입니까? (0) | 2023.09.20 |
---|---|
자바 프로젝트:ApplicationContext를 로드하지 못했습니다. (0) | 2023.09.20 |
저장 프로시저에 대한 입력으로 사용자 정의 유형을 전달하려면 어떻게 해야 합니까? (0) | 2023.09.20 |
알파벳을 어떻게 반복합니까? (0) | 2023.07.22 |
구성 맵 kubernetes 여러 환경 (0) | 2023.07.22 |