Files
multiprecision/Lab/operations.cpp
2023-04-21 23:06:09 +03:00

259 lines
7.8 KiB
C++

#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include "triple.h"
#include "global.h"
#include "operations.h"
using namespace std;
triple operations::add(triple& a, triple& b) {
if (a.negative && !b.negative) {
a.negative = false;
triple res = b - a;
return res;
}
if (!a.negative && b.negative) {
b.negative = false;
triple res = a - b;
return res;
}
if (a.negative && b.negative) {
a.negative = false;
b.negative = false;
triple res = a + b;
res.negative = true;
a.negative = true;
b.negative = true;
return res;
}
triple res;
int next = 0;
int int_size = max(a.integer.size(), b.integer.size());
int float_size = max(a.floating.size(), b.floating.size());
vector<int> int_result;
vector<int> floating_result;
while (a.integer.size() < int_size)
a.integer.insert(a.integer.begin(), 0);
while (b.integer.size() < int_size)
b.integer.insert(b.integer.begin(), 0);
while (a.floating.size() < float_size)
a.floating.push_back(0);
while (b.floating.size() < float_size)
b.floating.push_back(0);
for (auto av = a.floating.rbegin(), bv = b.floating.rbegin(); av != a.floating.rend() && bv != b.floating.rend(); ++av, ++bv) {
int sum = *av + *bv + next;
floating_result.insert(floating_result.begin(), sum % 10);
next = sum / 10;
}
for (auto av = a.integer.rbegin(), bv = b.integer.rbegin(); av != a.integer.rend() && bv != b.integer.rend(); ++av, ++bv) {
int sum = *av + *bv + next;
int_result.insert(int_result.begin(), sum % 10);
next = sum / 10;
}
if (next != 0) int_result.insert(int_result.begin(), next);
res.integer = int_result;
res.floating = floating_result;
return res;
}
triple operations::subtract(triple& a, triple& b) {
triple res;
int borrow = 0;
bool negative = false;
int int_size = max(a.integer.size(), b.integer.size());
int float_size = max(a.floating.size(), b.floating.size());
vector<int> int_result;
vector<int> floating_result;
while (a.integer.size() < int_size)
a.integer.insert(a.integer.begin(), 0);
while (b.integer.size() < int_size)
b.integer.insert(b.integer.begin(), 0);
while (a.floating.size() < float_size)
a.floating.push_back(0);
while (b.floating.size() < float_size)
b.floating.push_back(0);
if (a < b) {
swap(a, b);
negative = true;
}
if (a.negative && !b.negative) {
res = a + b;
res.negative = true;
return res;
}
else if (!a.negative && b.negative) {
res = a + b;
res.negative = false;
return res;
}
for (int i = float_size - 1, j = float_size - 1; i >= 0 || j >= 0; i--, j--) {
int digit1 = (i >= 0) ? a.floating[i] : 0;
int digit2 = (j >= 0) ? b.floating[j] : 0;
int diff = digit1 - digit2 - borrow;
if (diff < 0) {
diff += 10;
borrow = 1;
}
else borrow = 0;
floating_result.insert(floating_result.begin(), diff);
}
for (int i = int_size - 1, j = int_size - 1; i >= 0 || j >= 0; i--, j--) {
int digit1 = (i >= 0) ? a.integer[i] : 0;
int digit2 = (j >= 0) ? b.integer[j] : 0;
int diff = digit1 - digit2 - borrow;
if (diff < 0) {
diff += 10;
borrow = 1;
}
else borrow = 0;
int_result.insert(int_result.begin(), diff);
}
while (!int_result.empty() && int_result.front() == 0) int_result.erase(int_result.begin());
while (!floating_result.empty() && floating_result.back() == 0) floating_result.pop_back();
if (int_result.empty()) {
int_result.push_back(0);
}
res.negative = negative;
res.integer = int_result;
res.floating = floating_result;
return res;
}
triple operations::multiply(triple& a, triple& b) {
triple res;
vector<int> int_result, floating_result;
vector<int> num1, num2;
int decimal = a.floating.size() + b.floating.size();
num1 = a.integer;
num2 = b.integer;
num1.insert(num1.end(), a.floating.begin(), a.floating.end());
num2.insert(num2.end(), b.floating.begin(), b.floating.end());
vector<int> result(num1.size() + num2.size());
if (a.negative && !b.negative || !a.negative && b.negative) res.negative = true;
for (int i = a.integer.size() + a.floating.size() - 1; i >= 0; i--) {
int carry = 0;
for (int j = b.integer.size() + b.floating.size() - 1; j >= 0; j--) {
int prod = num1[i] * num2[j] + result[i + j + 1] + carry;
result[i + j + 1] = prod % 10;
carry = prod / 10;
}
result[i] += carry;
}
int i = 0;
for (auto it = result.rbegin(); it != result.rend() && i < decimal; it++, i++)
floating_result.insert(floating_result.begin(), *it);
i = 0;
for (auto it = result.begin(); it != result.end() && i < result.size() - decimal; it++, i++)
int_result.push_back(*it);
while (!int_result.empty() && int_result.front() == 0) int_result.erase(int_result.begin());
while (!floating_result.empty() && floating_result.back() == 0) floating_result.pop_back();
res.integer = int_result;
res.floating = floating_result;
return res;
}
triple operations::divide(triple& a, triple& b) {
vector<int> dividend;
vector<int> divisor;
for (auto i : a.integer) dividend.push_back(i);
for (auto i : a.floating) dividend.push_back(i);
for (auto i : b.integer) divisor.push_back(i);
for (auto i : b.floating) divisor.push_back(i);
if (a.floating.size() > b.floating.size()) {
int add = a.floating.size() - b.floating.size();
while (add--) divisor.push_back(0);
}
if (a.floating.size() < b.floating.size()) {
int add = b.floating.size() - a.floating.size();
while (add--) dividend.push_back(0);
}
triple tempb;
int count = 0;
triple result;
result.integer = { 0 };
result.floating = {};
triple one;
triple ten;
triple zero;
zero.integer = { 0 };
zero.floating = { 0 };
ten.integer = { 1, 0 };
ten.floating = {};
one.integer = { 1 };
one.floating = { 0 };
triple res = a;
int currentPrecision = 0;
while (!(res < b)) {
tempb = b;
res = res - tempb;
if (!res.negative) result = result + one;
}
result.floating.clear();
bool first = false;
res.negative = false;
while (currentPrecision < precision) {
res.negative = false;
while (res < b && res != zero && res != b) {
if (res.integer.empty() && res.floating.empty() || (res.integer.size() == 1 && res.integer.at(0) == 0) && (res.floating.size() == 1 && res.floating.at(0) == 0)) {
break;
}
if (first) result.floating.push_back(0);
first = true;
res = res * ten;
}
first = false;
count = 0;
while (!(res < b) && !(res == zero)) {
tempb = b;
res = res - tempb;
count++;
}
res.negative = false;
if (count != 0) result.floating.push_back(count);
currentPrecision++;
}
return result;
}
triple operator+(triple& a,triple& b) {
operations op;
triple res = op.add(a, b);
return res;
}
triple operator-(triple& a, triple& b) {
operations op;
triple res = op.subtract(a, b);
return res;
}
triple operator*(triple& a, triple& b) {
operations op;
triple res = op.multiply(a, b);
return res;
}
triple operator/(triple& a, triple& b) {
operations op;
triple res = op.divide(a, b);
return res;
}