05.02.2021, 00:35. Показов 472. Ответов 0
создал два класса чисел с фиксированной запятой, один с 13 двоичными цифрами после запятой (достаточно для 3-4 десятичных цифр после запятой), другой с 62 цифрами после запятой. отличаются эти два класса только парой констант и названием. Как сделать не через ctrl+c ctrl+v?
аааа придумал, надо создать общий класс потом ему конкретизировать расположение запятой. как удалить тему?
обратите внимание на строку 30 и строку 169
| C++ |
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
| #define ubuntu_os false
#define windows_os (!ubuntu_os)
#define safety_check true
#include <stdio.h>
typedef long double ez_real;//ez=ezsy
class unfloat_mili;
class mantisse;
const uint64_t uint_max = -1;//maximum value of uint64_t
const uint64_t half_uint_max = 1Ui64 << 63;//1000...0000 in binary
const int64_t low_32_bit_mark = uint_max >> 32;//000...000111...111 32 0-signs and 32 1-signs, constant for trick with & operator
const int64_t high_32_bit_mark = uint_max << 32;//111...111000...000 32 1-signs and 32 0-signs, constant for trick with & operator
const uint64_t max_int_sign = 1Ui64 << 62;//maximum sign that is not +-
//unfloat means not floating point, mili means enought accuracy for 1/1000-value
class unfloat_mili//=========================================================================================================================infloat_mili here
{
private:
typedef unfloat_mili current_type;
int64_t signs;
public:
unfloat_mili() { set_sign(0); }
unfloat_mili(int64_t num) { set_sign(num); }
unfloat_mili(ez_real val) { set_val(val); }
static const int64_t point_offset = 13;// = log2(8192) = log2(0x2000) = ln(0x2000) / ln(2), 13 signs past point
static const int64_t size_of_int = 64 - point_offset;
//полное совпадение ниже этой линии
static const int64_t minus_size_of_uint = 1 - size_of_int;//we need this constant for current division algorithm
static const int64_t past_point_marker = (~0Ui64) >> size_of_int;//00...0000.111...1 constant for & operation
static const int64_t one_code = 1 << point_offset;//=8192 = 0x2000
static const int64_t middle_offset = 32 - size_of_int;
static const char current_type_name[];
static const current_type one;
static const current_type null;
int64_t get_sign() { return signs; }
void set_sign(int64_t sign) { signs = sign; }
ez_real get_val() { return ((ez_real)signs) / one_code; }
void set_val(ez_real val) { signs = val * one_code; }
int64_t get_pre() { return signs >> point_offset; }
int64_t get_past() { return signs & past_point_marker; }
int64_t get_low32() { return signs & low_32_bit_mark; }
int64_t get_high32() { return signs >> 32; }
current_type operator= (ez_real val) { signs = val * one_code; return current_type(signs); }
current_type operator+ (current_type x) { return current_type(get_sign() + x.get_sign()); }
current_type operator- (current_type x) { return current_type(get_sign() - x.get_sign()); }
bool operator> (current_type x) { return get_sign() > x.get_sign(); }
bool operator< (current_type x) { return get_sign() < x.get_sign(); }
bool operator== (current_type x) { return get_sign() == x.get_sign(); }
bool operator>= (current_type x) { return get_sign() >= x.get_sign(); }
bool operator<= (current_type x) { return get_sign() <= x.get_sign(); }
current_type operator<< (int64_t x) { return current_type(get_sign() << x); }
current_type operator>> (int64_t x) { return current_type(get_sign() >> x); }
current_type operator- () { return current_type(-get_sign()); }
current_type operator* (current_type x)
{
int64_t preA = get_high32();
int64_t preB = x.get_high32();
uint64_t pastA = get_low32();
uint64_t pastB = x.get_low32();
return current_type(int64_t(((preA * preB) << size_of_int) + \
((preA * pastB) >> middle_offset) + \
((preB * pastA) >> middle_offset) + \
((pastA * pastB) >> point_offset)));
}
current_type operator/ (current_type x)
{
int64_t result = 0;
bool minus = false;
uint64_t divident = get_sign();
uint64_t divider = x.get_sign();
if (divident >= half_uint_max)//============= +- checking divident
{
minus = true;
divident = 0 - divident;
}
if (divider == 0)// zero-checking divider
{
if (minus) return current_type((int64_t)half_uint_max);
else return current_type((int64_t)~half_uint_max);
}
if (divider >= half_uint_max)// +- checking divider
{
minus = !minus;
divider = 0 - divider;
if (divider == half_uint_max)
{
divider >>= 1;
divident >>= 1;
}
}
int relative_divider_offset = 0;
//while (true)//==================== move divider's signs to the left
while (!(divider & max_int_sign))
{
divider <<= 1;
relative_divider_offset--;
#if safety_check
if (relative_divider_offset <= -64)//extra check for zero division
{
printf("\n\n fatal error with division algorithm\nclass %s, current_type operator/(current_type x)\n", current_type_name);
abort();
}
#endif
}
for (bool overload; relative_divider_offset <= point_offset; relative_divider_offset++)//===== calculating signs
{
overload = relative_divider_offset <= minus_size_of_uint;
if (divident >= divider)
{// we should write sign '1'
if (overload)
{//return maximum value
if (minus) return current_type((int64_t)half_uint_max);
else return current_type((int64_t)~half_uint_max);
}
else
{
divident -= divider;
result <<= 1;
result |= 1;
}
}
else
{//we should write sign '0'
if (overload)
{
//thats ok just do nothing
}
else
{
result <<= 1;
}
}
divident <<= 1;
}
if (minus) result = -result;
return current_type(result);
}
};
const char unfloat_mili::current_type_name[] = "unfloat_mili";
const unfloat_mili unfloat_mili::one = 1.l;
const unfloat_mili unfloat_mili::null = 0.l;
//mantisse means its something betwen -1.99999... and +1.99999...
class mantisse//==============================================================================================================mantisse here
{
private:
typedef mantisse current_type;
int64_t signs;
public:
mantisse() { set_sign(0); }
mantisse(int64_t num) { set_sign(num); }
mantisse(ez_real val) { set_val(val); }
static const int64_t size_of_int = 2;// (1 bit for +-) + (1 bit for integer part) = 2, we dont need more
static const int64_t point_offset = 64-size_of_int;// = 62. more-better, but we cant do it more.
//полное совпадение ниже этой линии
static const int64_t minus_size_of_uint = 1 - size_of_int;//we need this constant for current division algorithm
static const int64_t past_point_marker = (~0Ui64) >> size_of_int;//00.111...1 constant for & operation
static const int64_t one_code = 1i64 << point_offset;//
static const int64_t middle_offset = 32 - size_of_int;
static const char current_type_name[];
static const current_type one;
static const current_type null;
// http://cppstudio.com/post/2676/
int64_t get_sign() { return signs; }
void set_sign(int64_t sign) { signs = sign; }
ez_real get_val() { return ((ez_real)signs) / one_code; }
void set_val(ez_real val) { signs = val * one_code; }
int64_t get_pre() { return signs >> point_offset; }
int64_t get_past() { return signs & past_point_marker; }
int64_t get_low32() { return signs & low_32_bit_mark; }
int64_t get_high32(){ return signs >> 32; }
current_type operator= (ez_real val) { signs = val * one_code; return current_type(signs); }
current_type operator+ (current_type x) { return current_type(get_sign() + x.get_sign()); }
current_type operator- (current_type x) { return current_type(get_sign() - x.get_sign()); }
bool operator> (current_type x) { return get_sign() > x.get_sign(); }
bool operator< (current_type x) { return get_sign() < x.get_sign(); }
bool operator== (current_type x) { return get_sign() == x.get_sign(); }
bool operator>= (current_type x) { return get_sign() >= x.get_sign(); }
bool operator<= (current_type x) { return get_sign() <= x.get_sign(); }
current_type operator<< (int64_t x) { return current_type(get_sign() << x); }
current_type operator>> (int64_t x) { return current_type(get_sign() >> x); }
current_type operator- () { return current_type(-get_sign()); }
current_type operator* (current_type x)
{
int64_t preA = get_high32();
int64_t preB = x.get_high32();
uint64_t pastA = get_low32();
uint64_t pastB = x.get_low32();
return current_type (int64_t(((preA * preB) << size_of_int) +\
((preA * pastB) >> middle_offset) + \
((preB * pastA) >> middle_offset) + \
((pastA * pastB) >> point_offset)));
}
current_type operator/ (current_type x)
{
int64_t result = 0;
bool minus = false;
uint64_t divident = get_sign();
uint64_t divider = x.get_sign();
if (divident >= half_uint_max)//============= +- checking divident
{
minus = true;
divident = 0 - divident;
}
if (divider == 0)// zero-checking divider
{
if (minus) return current_type((int64_t)half_uint_max);
else return current_type((int64_t)~half_uint_max);
}
if (divider >= half_uint_max)// +- checking divider
{
minus = !minus;
divider = 0 - divider;
if (divider == half_uint_max)
{
divider >>= 1;
divident >>= 1;
}
}
int relative_divider_offset = 0;
//while (true)//==================== move divider's signs to the left
while (!(divider & max_int_sign))
{
divider <<= 1;
relative_divider_offset--;
#if safety_check
if (relative_divider_offset <= -64)//extra check for zero division
{
printf("\n\n fatal error with division algorithm\nclass %s, current_type operator/(current_type x)\n", current_type_name);
abort();
}
#endif
}
for (bool overload; relative_divider_offset <= point_offset; relative_divider_offset++)//===== calculating signs
{
overload = relative_divider_offset <= minus_size_of_uint;
if (divident >= divider)
{// we should write sign '1'
if (overload)
{//return maximum value
if (minus) return current_type((int64_t)half_uint_max);
else return current_type((int64_t)~half_uint_max);
}
else
{
divident -= divider;
result <<= 1;
result |= 1;
}
}
else
{//we should write sign '0'
if (overload)
{
//thats ok just do nothing
}
else
{
result <<= 1;
}
}
divident <<= 1;
}
if (minus) result = -result;
return current_type(result);
}
};
const char mantisse::current_type_name[] = "mantisse";
const mantisse mantisse::one = 1.l;
const mantisse mantisse::null = 0.l; |
|
Добавлено через 19 минут