数值计算溢出判断

数值计算溢出

在进行数值计算时可能会导致计算后的结果过大或过小,超出数值类型的范围,此处封装数据计算类,在计算前先对计算后的结果进行判断,防止溢出,并给出错误提醒

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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#ifndef _Overflow_Detection_Value_H_
#define _Overflow_Detection_Value_H_

#include <string>
#include <limits>

enum OverflowErrorCode
{
NoError = 0,
AdditionOverflow,
SubtractionOverflow,
MultiplicationOverflow,
DivisionOverflow
};

template<class T>
class TOverflowDetectionValue
{
public:
explicit TOverflowDetectionValue(T tValue) : m_tValue(tValue) { }
virtual ~TOverflowDetectionValue() { }
TOverflowDetectionValue(const TOverflowDetectionValue &tR)
{
m_tValue = tR.m_tValue;
}
TOverflowDetectionValue& operator =(const TOverflowDetectionValue &tR)
{
m_tValue = tR.m_tValue;
return *this;
}
inline TOverflowDetectionValue& operator =(const T &tR)
{
m_tValue = tR;
return *this;
}
inline TOverflowDetectionValue operator +(const TOverflowDetectionValue &tR)
{
if(m_tValue>0 && tR.m_tValue>0 && m_tValue > std::numeric_limits<T>::max()-tR.m_tValue)
{
m_eError = AdditionOverflow;
return TOverflowDetectionValue(std::numeric_limits<T>::max());
}
else if(m_tValue<0 && tR.m_tValue<0 && m_tValue < std::numeric_limits<T>::min()-tR.m_tValue)
{
m_eError = AdditionOverflow;
return TOverflowDetectionValue(std::numeric_limits<T>::min());
}
else
{
TOverflowDetectionValue tTmp;
tTmp.m_tValue = m_tValue + tR.m_tValue;
return tTmp;
}
}
inline TOverflowDetectionValue operator +(const T &tR)
{
return (*this) + TOverflowDetectionValue(tR);
}

inline TOverflowDetectionValue operator -(const TOverflowDetectionValue &tR)
{
if(m_tValue>0 && tR.m_tValue<0 && m_tValue > std::numeric_limits<T>::max()+tR.m_tValue)
{
m_eError = SubtractionOverflow;
return TOverflowDetectionValue(std::numeric_limits<T>::max());
}
else if(m_tValue<0 && tR.m_tValue>0 && m_tValue < std::numeric_limits<T>::min()+tR.m_tValue)
{
m_eError = SubtractionOverflow;
return TOverflowDetectionValue(std::numeric_limits<T>::min());
}
else
{
TOverflowDetectionValue tTmp;
tTmp.m_tValue = m_tValue - tR.m_tValue;
return tTmp;
}
}
inline TOverflowDetectionValue operator -(const T &tR)
{
return (*this) - TOverflowDetectionValue(tR);
}

inline TOverflowDetectionValue operator *(const TOverflowDetectionValue &tR)
{
if((m_tValue>0 && tR.m_tValue>0 && std::numeric_limits<T>::max()/m_tValue < tR.m_tValue)
|| (m_tValue<0 && tR.m_tValue<0 && std::numeric_limits<T>::max()/m_tValue > tR.m_tValue)) // MAX > a * b
{
m_eError = MultiplicationOverflow;
return TOverflowDetectionValue(std::numeric_limits<T>::max());
}
else if((m_tValue>0 && tR.m_tValue<0 && std::numeric_limits<T>::min()/m_tValue > tR.m_tValue)
|| (m_tValue<0 && tR.m_tValue>0 && std::numeric_limits<T>::min()/m_tValue < tR.m_tValue)) // MIN < a * b
{
m_eError = MultiplicationOverflow;
return TOverflowDetectionValue(std::numeric_limits<T>::min());
}
else
{
TOverflowDetectionValue tTmp;
tTmp.m_tValue = m_tValue * tR.m_tValue;
return tTmp;
}
}
inline TOverflowDetectionValue operator *(const T &tR)
{
return (*this) * TOverflowDetectionValue(tR);
}

inline TOverflowDetectionValue operator /(const TOverflowDetectionValue &tR)
{
if(tR.m_tValue == 0)
{
m_eError = DivisionOverflow;
return TOverflowDetectionValue(std::numeric_limits<T>::max());
}
TOverflowDetectionValue tTmp;
tTmp.m_tValue = m_tValue / tR.m_tValue;
return tTmp;
}
inline TOverflowDetectionValue operator /(const T &tR)
{
return (*this) / TOverflowDetectionValue(tR);
}

static inline void ResetErrorCode()
{
m_eError = NoError;
}
inline T get()
{
return m_tValue;
}
static inline OverflowErrorCode GetErrorCode()
{
OverflowErrorCode eRet = m_eError;
m_eError = NoError;
return eRet;
}
static inline std::string GetErrorMsgByErrorCode(OverflowErrorCode eCode)
{
if(eCode == NoError) { return "No error"; }
else if (eCode == AdditionOverflow) { return "Addition overflow"; }
else if (eCode == SubtractionOverflow) { return "Subtraction overflow"; }
else if (eCode == MultiplicationOverflow) { return "Multiplication overflow"; }
else if (eCode == DivisionOverflow) { return "Division overflowNoError"; }
else { return "Undefined error code"; }
}

private:
TOverflowDetectionValue(){ }
private:
T m_tValue;
static __thread OverflowErrorCode m_eError;
};

template<typename T>
__thread OverflowErrorCode TOverflowDetectionValue<T>::m_eError = NoError;

#endif