스터디/C++

[C++] 절댓값 빠르게 구하기

latter2005 2021. 2. 20. 23:39

C++ 에는 절댓값을 구할 수 있는 함수 abs 함수가 있습니다.

 

abs - C++ Reference

12345678910111213 /* abs example */ #include /* printf */ #include /* abs */ int main () { int n,m; n=abs(23); m=abs(-11); printf ("n=%d\n",n); printf ("m=%d\n",m); return 0; }

www.cplusplus.com

이 함수를 이용하게 되면 함수 호출에 대한 페널티를 받기 때문에 if 혹은 수의 특성을 이용해서 구해 시간을 줄일 수 있습니다.

 

#define bit_abs(x) ~x + 1

정수형인 int, long long의 경우 왼쪽 끝의 비트가 부호를 나타내므로 0x80000000 & x를 통해 부호를 알 수 있습니다.

정수형 결과

#define bit_fabs(x) (*reinterpret_cast<std::uint64_t*>(&x)) &= 0x7fffffffffffffff

실수형 double, float의 경우 메모리 기준으로 64, 32 비트 형식으로 타입 캐스팅 해준 후 최상단 비트가 sign을 나타내므로 0x7ffffffff & x을 통해 부호를 변경할 수 있습니다.

실수형 결과

비트를 활용하거나 if문을 활용하는 것이 abs, fabs보다 더 빠른 것을 볼 수 있습니다. 비트와 if문을 활용하는 경우 거의 비슷한 결과를 얻을 수 있었습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <iostream>
#include <algorithm>
#include <random>
#include <ctime>
#include <Windows.h>
#define MAX 4000000
#define bit_abs(x) x&0x80000000 ? -(x) : x
#define bit_fabs(x) (*reinterpret_cast<std::uint64_t*>(&x)) &= 0x7fffffffffffffff
using namespace std;
template<typename T = int>
void use_if(T ary[]) {
    for (int i = 0; i < MAX; i++) {
        if (ary[i] < 0)
            ary[i] = -ary[i];
    }
}
template<typename T = int>
void use_bitop(T ary[]) {
    for (int i = 0; i < MAX; i++)
        ary[i] = bit_abs(ary[i]);
}
template<typename T = int>
void use_bitif(T ary[]) {
    for (int i = 0; i < MAX; i++)
        if (ary[i] & 0x80000000)
        ary[i] = -ary[i];
}
template<typename T = int>
void use_abs(T ary[]) {
    for (int i = 0; i < MAX; i++)
        ary[i] = abs(ary[i]);
}
template<typename T = double>
void use_fabs(T ary[]) {
    for (int i = 0; i < MAX; i++)
        ary[i] = fabs(ary[i]);
}
template<typename T = double>
void use_bit_fabs(T ary[]) {
    for (int i = 0; i < MAX; i++)
        bit_fabs(ary[i]);
}
template<typename T, typename F>
void query(T ary[], F f, const char *s) {
    T tmp[MAX];
    memcpy(tmp, ary, sizeof ary);
    double time;
    bool b;
    __int64 freq, start, end;
    BOOL condition;
    if (condition = QueryPerformanceFrequency((_LARGE_INTEGER*)&freq))
        QueryPerformanceCounter((_LARGE_INTEGER*)&start);
 
    f(tmp);
 
    if (condition) {
        QueryPerformanceCounter((_LARGE_INTEGER*)&end);
        time = (float)((double)(end - start) / freq * 1000);
        printf("use %s => time : %lf\n", s, time);
    }
}
int main() {
    
    mt19937 gen(12345);
    
    /*uniform_int_distribution<int> dist(-0x7fffffff, 0x7fffffff);
    int ary[MAX], tmp[MAX];
    for (int i = 0; i < MAX; i++) {
        ary[i] = dist(gen);
    }
    
    
    query(ary, &use_bitop<int>, "bit");
    query(ary, &use_bitif<int>, "bitif");
    query(ary, &use_if<int>, "if");
    query(ary, &use_abs<int>, "abs");*/
    
    
    uniform_real_distribution<double>dist(-0x7fffffff0x7fffffff);
    double ary[MAX], tmp[MAX];
    for (int i = 0; i < MAX; i++) {
        ary[i] = dist(gen);
    }
    query(ary, &use_if<double>"if");
    query(ary, &use_bit_fabs<double>"bit");
    query(ary, &use_fabs<double>"fabs");
    
}
 
cs
반응형

'스터디 > C++' 카테고리의 다른 글

[C++] struct, pair 비교  (0) 2020.12.17