lab3
/
BigRealNumber.cpp
219 строк · 6.0 Кб
1#include "BigRealNumber.h"
2
3BigRealNumber::BigRealNumber() {
4intPrt = new short[1000];
5fractPrt = new short[1000];
6intPrtLen = 0;
7fractPrtLen = 0;
8isNegative = false;
9}
10
11BigRealNumber::BigRealNumber(const string &numb) {
12intPrt = new short[1000];
13fractPrt = new short[1000];
14
15isNegative = numb[0] == '-';
16intPrtLen = (int) numb.find('.');
17if (isNegative) {
18intPrtLen--;
19}
20fractPrtLen = (int) numb.length() - intPrtLen - 1;
21if (isNegative) {
22fractPrtLen--;
23}
24
25int j = isNegative ? 1 : 0;
26// копирование целой части
27for (int i = intPrtLen - 1; i >= 0; i--, j++) {
28intPrt[i] = (short) (numb.at(j) - '0');
29}
30j++;
31
32// копирование дробной части
33for (int i = fractPrtLen - 1; i >= 0; i--, j++) {
34fractPrt[i] = (short) (numb.at(j) - '0');
35}
36}
37
38BigRealNumber::~BigRealNumber() {
39delete fractPrt;
40delete intPrt;
41}
42
43string BigRealNumber::toString() const {
44string numb;
45if (isNegative) {
46numb.append(1, '-');
47}
48for (int i = intPrtLen - 1; i >= 0; i--) {
49numb.append(1, (char) ('0' + (int) intPrt[i]));
50}
51numb.append(1, '.');
52for (int i = fractPrtLen - 1; i >= 0; i--) {
53numb.append(1, (char) ('0' + (int) fractPrt[i]));
54}
55
56return numb;
57}
58
59BigRealNumber &BigRealNumber::operator=(const BigRealNumber &other) {
60isNegative = other.isNegative;
61fractPrtLen = other.fractPrtLen;
62intPrtLen = other.intPrtLen;
63
64fractPrt = new short[1000];
65intPrt = new short[1000];
66
67for (int i = 0; i < fractPrtLen; i++) {
68fractPrt[i] = other.fractPrt[i];
69}
70for (int i = 0; i < intPrtLen; i++) {
71fractPrt[i] = other.fractPrt[i];
72}
73
74return *this;
75}
76
77BigRealNumber BigRealNumber::operator+(const BigRealNumber &other) const {
78// this + other
79// -this + other
80// this + (-other)
81// -this + (-other)
82
83if (!(isNegative) && other.isNegative) { // this + (-other)
84return *this - other;
85} else if (isNegative && !other.isNegative) { // -this + other
86return other - *this;
87}
88
89BigRealNumber res;
90res.isNegative = isNegative;
91
92// сложение дробных частей
93short trans = addArraysToBRL(*this, other,
94res, true,
95false, 0);
96// сложение целых частей
97addArraysToBRL(*this, other,
98res, false,
99false, trans);
100
101return res;
102}
103
104BigRealNumber BigRealNumber::operator-(const BigRealNumber &other) const {
105// this - other
106// -this - other
107// -this - (-other)
108// this - (-other)
109
110if ((isNegative && other.isNegative) || (!(isNegative) && other.isNegative)) {
111return *this + other; // -this - other; this - (-other)
112} else if (isNegative && other.isNegative) {
113// -this - (-other)
114BigRealNumber res = other;
115res.isNegative = false;
116res = res - *this;
117return res;
118}
119
120BigRealNumber res;
121}
122
123// -------- вспомогательные методы --------------
124void BigRealNumber::appendToInt(short number) {
125if (intPrtLen + 1 >= 1000) {
126throw runtime_error("Ошибка вычисления: целая часть "
127"выходного числа содержит более 1000 цифр");
128}
129intPrt[intPrtLen++] = number;
130}
131
132bool BigRealNumber::appendToFract(short number) {
133if (fractPrtLen + 1 >= 1000) {
134return false;
135}
136fractPrt[fractPrtLen++] = number;
137return true;
138}
139
140short BigRealNumber::addArraysToBRL(
141const BigRealNumber &term1,
142const BigRealNumber &term2,
143BigRealNumber &res,
144bool addToFract,
145bool minusTerm2,
146short transfer
147) const {
148int len1;
149int len2;
150if (addToFract) {
151len1 = term1.fractPrtLen;
152len2 = term2.fractPrtLen;
153} else {
154len1 = term1.intPrtLen;
155len2 = term2.intPrtLen;
156}
157
158short *bg; // больший массив
159short *sm; // меньший массив
160// если term2 наименьший массив
161bool minIsTerm2;
162// распределить массивы по длине
163if (len1 > len2) {
164bg = addToFract ? term1.fractPrt : intPrt;
165sm = addToFract ? term2.fractPrt : term2.intPrt;
166minIsTerm2 = true;
167} else {
168bg = addToFract ? term2.fractPrt : term2.intPrt;
169sm = addToFract ? term1.fractPrt : intPrt;
170minIsTerm2 = false;
171}
172
173// распределить длинны
174if (addToFract) {
175len1 = max(term1.fractPrtLen, term2.fractPrtLen);
176len2 = min(term1.fractPrtLen, term2.fractPrtLen);
177} else {
178len1 = max(term1.intPrtLen, term2.intPrtLen);
179len2 = min(term1.intPrtLen, term2.intPrtLen);
180}
181
182for (int i = 0, j = 0; i < len1; i++) {
183short n = transfer;
184// при сложении целых частей, начало меньшего массива прикладывается
185// к началу большего
186// при сложении дробных частей, конец меньшего массива прикладывается к
187// концу большего
188// пример 90.90; 1000.001
189// 0001.100
190// 09 . 09
191if ((i < len2 && !addToFract) || (i >= len1 - len2 && addToFract)) {
192n += sm[j++] * std::pow(-1, minIsTerm2 && minusTerm2);
193}
194n += bg[i] * std::pow(-1, !minIsTerm2 && minusTerm2);
195
196transfer = n > 9;
197if (n < 0 && (addToFract || i < len1 - 1)) {
198n += 10;
199transfer = -1;
200}
201n %= 10;
202if (addToFract) {
203if (!res.appendToFract(n)) {
204break;
205}
206} else {
207res.appendToInt(n);
208}
209}
210
211if (transfer > 0 && !addToFract) {
212res.appendToInt(transfer);
213}
214
215return transfer;
216}
217
218// 0.0 - 1.0
219// 0-0
220