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
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
| #pragma hdrstop
#include "stringnumber.h"
#include <math.h>
#pragma package(smart_init)
strnum::strnum(){ //конструктор без параметров по умолчанию
string="0";
flag=false;
return;
}
strnum::strnum(int Qs){ //конструктор из целого числа
if(Qs>=0){flag=false;}else{flag=true;} // установка флага отрицательного числа
string=IntToStr(abs(Qs)); // запись модуля числа в строку
return;
}
strnum::strnum(double Qs){ //конструктор из вещественного числа
if(Qs>=0){flag=false;}else{flag=true;} // установка флага отрицательного числа
string=FloatToStr(fabs(Qs)); // запись модуля числа в строку
return;
}
strnum::strnum(char* Qs){ //конструктор из строки
flag=false;
string=Qs;
try{
string.ToDouble();}
catch(...){
string="0";}
if(string[1]=='-'){
flag=true;string.Delete(1,1);} // установка флага отрицательного числа
return;
}
strnum::strnum(const strnum & Qs){ // конструктор копирования
string=Qs.string;
flag=Qs.flag;
try{
string.ToDouble();}
catch(...){
string="0";}
return;
}
int strnum::dot(){ // возвращает позицию точки с конца
if((string.Pos('.')!=0))
return string.Length()-string.Pos('.');
else
return 0;
}
strnum strnum::operator =(strnum Qs){ // присвоение
string=Qs.string;
flag=Qs.flag;
return *this;
}
strnum strnum::operator =(int Qs){ // присвоение к целому (аналогично копированию)
if(Qs>=0){flag=false;}else{flag=true;}
string=IntToStr(abs(Qs));
return *this;
}
strnum strnum::operator =(double Qs){ // присвоение к вещественному (аналогично копированию)
if(Qs>=0){flag=false;}else{flag=true;}
string=FloatToStr(fabs(Qs));
return *this;
}
strnum strnum::operator =(char* Qs){ // присвоение к строке (аналогично копированию)
flag=false;
string=Qs;
try{
string.ToDouble();}
catch(...){
string="0";}
if(string[1]=='-'){flag=true;string.Delete(1,1);}
return *this;
}
strnum strnum::operator +(strnum &Qs){ // сложение
strnum temp(*this); // вспомогательная переменная (результат)
if((temp.flag)&&(!Qs.flag)) { // -A+B
temp.flag=false;
return Qs-temp; // => B-A
}
if((!temp.flag)&&(Qs.flag)) { // A+(-B)
Qs.flag=false;
return temp-Qs; // => B-A
}
if((temp.flag)&&(Qs.flag)) { // -A+(-B)
Qs.flag=false;
temp.flag=false;
return -(temp+Qs); // => -(A+B)
}
int la,lb,a,b,n; // длина чисел, цифры, сумма цифр
int dota,dotb,dotk; // позиция точек
dota=temp.dot();
dotb=Qs.dot();
dotk=dota-dotb; // разность разрядов
if(dota!=0)
temp.string.Delete(temp.string.Pos('.'),1); // удаление точек
if(dotb!=0)
Qs.string.Delete(Qs.string.Pos('.'),1);
if(dotk<0){
temp.addzerob(-dotk); // дописывание сзади нулей
}
if(dotk>0){
Qs.addzerob(dotk); // дописывание сзади нулей
}
la=temp.string.Length()+1;
lb=Qs.string.Length()+1; // добавляем спереди по одному нулю,
temp.addzero(la); // на случай увеличения разряда
Qs.addzero(lb);
if (la>=lb){Qs.addzero(la);}else{temp.addzero(lb);la=lb;} // выравниваем числа
//if(Qs.string>temp.string){return Qs+temp;} // если правое больше, то меняем местами
for (int i = la; i!=0; i--) { // начиная с первого разряда (с конца)
a=temp.string[i]-48; // выделяем цифру из символа (-48 - константа)
b=Qs.string[i]-48;
n=a+b; // складываем цифры
if(n>=10){ // если больше 10, то
n=n-10; // выносим единицы
temp.string[i]=n+48;
temp.string[i-1]=temp.string[i-1]+1; // а соседний разряд увеличиваем на 1
}else{
temp.string[i]=n+48;
}
}
if(dotb>dota){ // вставка точки на правильную позицию
if(dotb!=0)temp.string.Insert('.',temp.string.Length()-dotb+1);
}else{
if(dotb<dota){
if(dota!=0)temp.string.Insert('.',temp.string.Length()-dota+1);
}else{
if(dota!=0)temp.string.Insert('.',temp.string.Length()-dotk);
}
}
temp.cutzero(); // вырезаем нули
return temp; // возвращаем ответ
}
strnum strnum::operator +(int Qs){ // сложение с числом
strnum temp(*this);
strnum temp2(Qs); // создаем путем копирования
return temp+temp2; // вызываем стандартный оператор
}
strnum strnum::operator +(double Qs){ // сложение с числом
strnum temp(*this);
strnum temp2(Qs); // создаем путем копирования
return temp+temp2; // вызываем стандартный оператор
}
strnum strnum::operator -(){ // отрицание (умножение на -1)
flag=!flag; // просто меняем флаг
return *this;
}
strnum strnum::operator -(strnum &Qs){ // вычитание
strnum temp(*this),temp0(*this),temp2(Qs); // вспомогательная переменная (результат)
if((temp.flag)&&(!Qs.flag)) { // -A-B
Qs.flag=false;
temp.flag=false;
return -(Qs+temp); // => -(A+B)
}
if((!temp.flag)&&(Qs.flag)) { // A-(-B)
Qs.flag=false;
return temp+Qs; // => A+B
}
if((temp.flag)&&(Qs.flag)) { // -A-(-B)
Qs.flag=false;
temp.flag=false;
return (Qs-temp); // => B-A
}
int la,lb,a,b,n;
int dota,dotb,dotk; // позиция точек
dota=temp.dot();
dotb=Qs.dot();
dotk=dota-dotb; // разность разрядов
if(dota!=0)
temp.string.Delete(temp.string.Pos('.'),1); // удаление точек
if(dotb!=0)
Qs.string.Delete(Qs.string.Pos('.'),1);
if(dotk<0){
temp.addzerob(-dotk); // дописывание сзади нулей
}
if(dotk>0){
Qs.addzerob(dotk); // дописывание сзади нулей
}
la=temp.string.Length()+1;
lb=Qs.string.Length()+1; // добавляем спереди по одному нулю,
temp.addzero(la); // на случай увеличения разряда
Qs.addzero(lb);
if (la>=lb){Qs.addzero(la);}else{temp.addzero(lb);la=lb;}
if(Qs.string>temp.string){ // если второе больше, то
temp2.flag=false;
temp0.flag=false;
return -(temp2-temp0); // -(B-A)
}
for (int i = la; i!=0; i--) {
a=temp.string[i]-48;
b=Qs.string[i]-48;
n=a-b;
if(n<0){ // если надо занять в соседнем разряде
n=n+10;
temp.string[i]=n+48;
temp.string[i-1]=temp.string[i-1]-1; // вычитаем 10ку
}else{
temp.string[i]=n+48;
}
}
if(dotb>dota){ // вставка точки на правильную позицию
if(dotb!=0)temp.string.Insert('.',temp.string.Length()-dotb+1);
}else{
if(dotb<dota){
if(dota!=0)temp.string.Insert('.',temp.string.Length()-dota+1);
}else{
if(dota!=0)temp.string.Insert('.',temp.string.Length()-dotk);
}
}
temp.cutzero(); // вырезаем нули
return temp; // возвращаем ответ
}
strnum strnum::operator -(int Qs){ // вычитание целого числа
strnum temp(*this);
strnum temp2(Qs); // путем копирования
return temp-temp2; // возвращаем разность
}
strnum strnum::operator -(double Qs){ // вычитание вещественного числа
strnum temp(*this);
strnum temp2(Qs); // путем копирования
return temp-temp2; // возвращаем разность
}
strnum strnum::operator *(int Qs){ // умножение на целое число
strnum temp(*this);
strnum temp2(Qs); // путем копирования
return temp*temp2; // возвращаем произведение
}
strnum strnum::operator *(double Qs){ // умножение на вещественное число
strnum temp(*this);
strnum temp2(Qs); // путем копирования
return temp*temp2; // возвращаем произведение
}
strnum strnum::operator *(strnum &Qs){ // умножение
strnum temp; // промежуточное слагаемое
strnum res; // конечный результат
int la,lb;
int dota,dotb,dotk; // позиция точек
dota=dot();
dotb=Qs.dot();
dotk=dota+dotb; // сумма разрядов
if(dota!=0)
string.Delete(string.Pos('.'),1); // удаление точек
if(dotb!=0)
Qs.string.Delete(Qs.string.Pos('.'),1);
la= Qs.string.Length();
lb= string.Length();
if(string>Qs.string){return Qs**this;}
for(int i=la;i>=1;i--){ // начиная с цифр первого числа
for(int j=lb;j>=1;j--){ // умножаем на каждую цифру второго
strnum k; // произведение двух цифр
k=(string[j]-48)*(Qs.string[i]-48)*pow(10,lb-j); // pow - для правильного порядка
temp=temp+k; // складываем получившееся слагаемое
}
// if(lb>la)la=lb;
for(int ii=1;ii<=la-i;ii++) // сдвигаем слагаемые как лесенку
temp.string.Insert("0",temp.string.Length()+1); // путем добавления в конец нулей
res=res+temp; // добавляем слагаемое к сумме
temp=0; // обнуляем промежуточное
}
if(dotk!=0)
res.string.Insert('.',res.string.Length()-dotk+1);
if(flag==Qs.flag) // если одного знака, то
return res; // возвращаем положительный результат
else
return -res; // иначе отрицательный
}
strnum strnum::falsedel (strnum &Qs){ // деление вычитаем
strnum temp1(*this);
strnum temp2(Qs);
strnum res;
temp1.flag=0; // убираем флаги
temp2.flag=0;
while (!temp1.flag){ // пока можем вычитать
temp1=temp1-temp2;
res=res+1; // увеличиваем результат на 1
}
if(temp1.flag)res=res-1; // если вычли больше, то уменьшаем на 1
return res;
}
strnum strnum::operator /(strnum &Qs){ // деление (столбиком)
strnum temp,tmp;
strnum r,lres,res;
bool flag1=flag,flag2=Qs.flag; // запоминаем знаки чисел
int dota,dotb,dotk; // позиция точек
cutzero(); // удаляем лишние нули
Qs.cutzero();
if(Qs.string=="0"){string="бесконечность =)";return *this;}
dota=dot(); // определяем позицию точек
dotb=Qs.dot();
if(dota!=0)
string.Delete(string.Pos('.'),1); // удаление точек
if(dotb!=0)
Qs.string.Delete(Qs.string.Pos('.'),1);
addzerob(dotb+1); // дописывание сзади нулей
Qs.addzerob(dota+1);
*this=*this*100000000000000.; // точность деления (6 знаков)
r=0; // остаток от деления
for(int i = 1; i <= string.Length(); ++i) {
r = r*10;
r= r + StrToInt(string[i]); // сносим цифру
lres = r.falsedel(Qs); // находим цифру частного
res.string=res.string+lres.string; // записываем в результат
tmp=lres*Qs ; // вычитаем в столбике
r =r- tmp; // новый остаток
}
res.string.Insert(".",res.string.Length()-13);
if(flag1==flag2) // если одного знака, то
return res; // возвращаем положительный результат
else
return -res; // иначе отрицательный
}
strnum strnum::operator /(int Qs){ // деление на целое число (столбиком)
strnum temp(Qs);
return *this/temp;
}
strnum strnum::operator /(double Qs){ // деление на вещественное число (столбиком)
strnum temp(Qs);
return *this/temp;
}
strnum strnum::addzero(int k){ // добавление нулей спереди
strnum temp(*this);
while (temp.string.Length()<k) // пока длина не станет k
temp.string.Insert("0",1); // приписываем спереди нолик
string=temp.string;
return *this;
}
strnum strnum::addzerob(int k){ // добавление нулей сзади
strnum temp(*this);
for(int i=0;i<k;i++)
temp.string.Insert("0",temp.string.Length()+1); // приписываем сзади нолик
string=temp.string;
return *this;
}
strnum strnum::cutzero(){ // удаление нулей
while ((string!="")&&(string[1]=='0')) // пока спереди есть нули
string.Delete(1,1); // удаляем
while ((string!="")&&(string[string.Length()]=='0')&&(string.Pos('.')!=0)) // пока спереди есть нули
string.Delete(string.Length(),1); // удаляем
if((string!="")&&(string[string.Length()]=='.'))string.Delete(string.Length(),1);
if(string==""){string="0";} // если ничего не осталось, то вернём 0
return *this;
}
AnsiString strnum::astext(){ // вывод как текст
cutzero(); // уберём нули, если они есть
if(flag){return ("-"+string);} // если отрицательное напишем минус
return string;
} |