Hi I need help creating a < operator and Im not sure how.
#include "biguint.h"
#include <string>
#include <cstdlib>
#include <iostream>
biguint::biguint()
{
for(size_t i = 0; i < CAPACITY; i++){
data_[i]=0;
}
}
biguint::biguint(const std::string &s){
int templeng = s.length();
for(size_t i = 0; i < templeng; i++){
data_[i] = s[templeng -i - 1] -'0';
}
for(size_t i = templeng; i < CAPACITY; i++){
data_[i]=0;
}
}
unsigned short biguint::operator [](std::size_t pos) const{
unsigned short i = 0;
if(pos >= 0 && pos < CAPACITY){
i = data_[pos];
}
return i;
}
std::ostream& operator <<(std::ostream& out, const biguint& b)
{
for (int i = biguint::CAPACITY; i > 0; i--) {
out<<b[i-1];
}
return out;
}
void biguint::operator += (const biguint & b){
int k = 0;
int temp = 0;
for (size_t i = 0; i < CAPACITY; i++) {
temp = data_[i]+b.data_[i];
if(temp >= 10){
data_[i] = temp-10;
data_[i+1]+=1;
}
else{
data_[i]=temp;
}
}
}
biguint operator + (const biguint & lhs, const biguint & rhs)
{
int temp;
bool remainder = false;
std::string result = "";
std::string reverse = "";
if(lhs.CAPACITY != rhs.CAPACITY)
{
return biguint("0");
}
for(int i =0; i < (int)lhs.CAPACITY;i++)
{
temp = lhs[i]+rhs[i];
if(remainder)
{
temp++;
remainder = false;
}
if(temp<10)
{
result = result + std::to_string(temp);
}
else {
result += std::to_string(temp - 10);
remainder = true;
}
}
for (int i = result.size() - 1; i >= 0; i--) {
reverse += result[i];
}
return biguint(reverse);
}
int biguint::compare(const biguint & b) const
{
return this->toStdString().compare(b.toStdString());
}
std::string biguint::toStdString() const
{
bool start = false;
std::string result = "";
for (int i = (int) this->CAPACITY - 1; i >= 0; i--) {
if (this->data_[i] == 0 && !start) {
if (this->CAPACITY == 1)
result += std::to_string(this->data_[i]);
continue;
}
else {
start = true;
result += std::to_string(this->data_[i]);
}
}
return result;
}
bool operator < (const biguint & lhs, const biguint & rhs)
{
}
This my .cpp file Im kind of lost on how to create < operator. I have created the +,+=, and two string but I'm unsure of how to create the <. Im not sure how to access those numbers for example biguint one("233") how would i access that number
Tl;dr: Try to compare digit by digit while handling mismatched length cases.
Say your given any 2 numbers:
num1 = 12345
num2 = 57632
The intuitive way for you to determine that which is bigger:
Compare them starting from the most significant digit(eg. here 5 > 1)
When equal compare the next significant digit(eg. if the numbers were 92 and 93, you would have compared 2 < 3 to get your answer.
The only difference is here individual digits are stored in an array.
P.S. Your compare seems to do a lexicographic compare - Is that really what you want?
Related
My code is here
//RSA.cpp
#include <iostream>
#include <cstring>
#include <ctime>
#include <random>
#include <vector>
#include <string>
#include "BigNum.hpp"
using namespace std;
BigNum mygcd(BigNum a, BigNum b)
{
while(a != b)
{
if(a>b)
{
a = a - b;
}
else
{
b = b - a;
}
}
return a;
}
BigNum prime(int n)
{
vector<BigNum> ans;
ans.push_back(BigNum(2));
ans.push_back(BigNum(3));
for (int i = 0; i < n; i++)
{
BigNum addend = 1;
for (auto j : ans)
{
addend = addend * j;
}
ans.push_back(addend + 1);
}
return ans[ans.size() - 1];
}
BigNum exgcd(BigNum a, BigNum b, BigNum &x, BigNum &y)
{
if (b == 0)
{
x = 1, y = 0;
return a;
}
BigNum g = exgcd(b, a - (a / b) * b, x, y);
BigNum t;
t = x;
x = y;
y = t - a / b * y;
return g;
}
BigNum niyuan(BigNum a, BigNum b)
{
BigNum x, y;
BigNum aa = exgcd(a, b, x, y);
return (x + b) - ((x + b) / b) * b;
}
vector<BigNum> yinshu(BigNum n)
{
vector<BigNum> ans;
int a = 2;
while (n / 2 > a)
{
if (n % a == 0)
{
ans.push_back(a);
}
a++;
}
return ans;
}
vector<int> ToBit(BigNum obj){
vector<int> r;
while (obj != 0){
r.push_back( (obj - (obj / 2) * 2 == 0) ? 0 : 1 );
obj = obj / 2;
}
return r;
}
BigNum jiami(BigNum e, int i, BigNum n)
{
BigNum addend = i;
BigNum result = 1;
vector<int>bitE = ToBit(e);
int now = 0;
while (now != bitE.size())
{
if (bitE[now])
{
result = addend * result;
result = result - (result / n) * n;
}
addend = addend * addend;
now = now + 1;
}
return result;
}
BigNum jiemi(BigNum d, BigNum i, BigNum n)
{
BigNum addend = i;
BigNum result = 1;
vector<int>bitD = ToBit(d);
int now = 0;
while (now != bitD.size())
{
if (bitD[now])
{
result = addend * result;
result = result - (result / n) * n;
}
addend = addend * addend;
now = now + 1;
}
return result;
}
int main()
{
srand(time(0));
BigNum p = prime(rand() % 20 + 1);
srand(time(0));
BigNum q = prime(rand() % 20 + 1);
BigNum N = p * q;
BigNum r = (p - 1) * (q - 1);
sss:
srand(time(0));
BigNum e = random() + 2;
if (mygcd(e, r) - BigNum(1) > 0)
goto sss;
vector<BigNum> yinshus = yinshu(r);
BigNum d = BigNum(niyuan(e, r));
cout << "Alice send(" << N << ',' << e << ")to Bob" << endl;
cout << "Please input your massage:";
string m;
cin >> m;
vector<int> message;
for (auto i : m)
{
message.push_back((int)i);
}
vector<BigNum> miwen;
for (auto i : message)
{
miwen.push_back(jiami(e, i, N));
}
cout << "coded text:";
for (auto i : miwen)
{
cout << i << " ";
}
vector<BigNum> minwen;
for (auto i : miwen)
{
minwen.push_back(jiemi(d, i, N));
}
cout << "明文:";
for (auto i : minwen)
{
cout << i << " ";
}
cout << endl;
}
I used a self-defined data structure called BigNum in order to store some large integers without them overflowing.
//BigNum.hpp
#include <iostream>
#include <cstring>
#include <string>
#include <iomanip>
#include <algorithm>
using namespace std;
#define MAXN 9999
#define MAXSIZE 10
#define DLEN 4
class BigNum
{
private:
int a[999];
int len;
public:
BigNum()
{
len = 1;
memset(a, 0, sizeof(a));
}
BigNum(const int);
BigNum(const char *);
BigNum(const BigNum &);
BigNum &operator=(const BigNum &);
friend istream &operator>>(istream &, BigNum &);
friend ostream &operator<<(ostream &, BigNum &);
BigNum operator+(const BigNum &) const;
BigNum operator-(const BigNum &) const;
BigNum operator*(const BigNum &) const;
BigNum operator/(const int &) const;
BigNum operator/(const BigNum &) const;
BigNum operator^(const int &) const;
int operator%(const int &) const;
bool operator>(const BigNum &T) const;
bool operator>(const int &t) const;
bool operator<(const BigNum &) const;
bool operator<=(const BigNum &) const;
bool operator>=(const BigNum &) const;
bool operator==(const BigNum &) const;
bool operator!=(const BigNum &) const;
void print();
};
BigNum::BigNum(const int b)
{
int c, d = b;
len = 0;
memset(a, 0, sizeof(a));
while (d > MAXN)
{
c = d - (d / (MAXN + 1)) * (MAXN + 1);
d = d / (MAXN + 1);
a[len++] = c;
}
a[len++] = d;
}
BigNum::BigNum(const char *s)
{
int t, k, index, l, i;
memset(a, 0, sizeof(a));
l = strlen(s);
len = l / DLEN;
if (l % DLEN)
len++;
index = 0;
for (i = l - 1; i >= 0; i -= DLEN)
{
t = 0;
k = i - DLEN + 1;
if (k < 0)
k = 0;
for (int j = k; j <= i; j++)
t = t * 10 + s[j] - '0';
a[index++] = t;
}
}
BigNum::BigNum(const BigNum &T) : len(T.len)
{
int i;
memset(a, 0, sizeof(a));
for (i = 0; i < len; i++)
a[i] = T.a[i];
}
BigNum &BigNum::operator=(const BigNum &n)
{
int i;
len = n.len;
memset(a, 0, sizeof(a));
for (i = 0; i < len; i++)
a[i] = n.a[i];
return *this;
}
istream &operator>>(istream &in, BigNum &b)
{
char ch[MAXSIZE * 4];
int i = -1;
in >> ch;
int l = strlen(ch);
int count = 0, sum = 0;
for (i = l - 1; i >= 0;)
{
sum = 0;
int t = 1;
for (int j = 0; j < 4 && i >= 0; j++, i--, t *= 10)
{
sum += (ch[i] - '0') * t;
}
b.a[count] = sum;
count++;
}
b.len = count++;
return in;
}
ostream &operator<<(ostream &out, BigNum &b)
{
int i;
cout << b.a[b.len - 1];
for (i = b.len - 2; i >= 0; i--)
{
cout.width(DLEN);
cout.fill('0');
cout << b.a[i];
}
return out;
}
BigNum BigNum::operator+(const BigNum &T) const
{
BigNum t(*this);
int i, big;
big = T.len > len ? T.len : len;
for (i = 0; i < big; i++)
{
t.a[i] += T.a[i];
if (t.a[i] > MAXN)
{
t.a[i + 1]++;
t.a[i] -= MAXN + 1;
}
}
if (t.a[big] != 0)
t.len = big + 1;
else
t.len = big;
return t;
}
BigNum BigNum::operator-(const BigNum &T) const
{
int i, j, big;
bool flag;
BigNum t1, t2;
if (*this > T)
{
t1 = *this;
t2 = T;
flag = 0;
}
else
{
t1 = T;
t2 = *this;
flag = 1;
}
big = t1.len;
for (i = 0; i < big; i++)
{
if (t1.a[i] < t2.a[i])
{
j = i + 1;
while (t1.a[j] == 0)
j++;
t1.a[j--]--;
while (j > i)
t1.a[j--] += MAXN;
t1.a[i] += MAXN + 1 - t2.a[i];
}
else
t1.a[i] -= t2.a[i];
}
t1.len = big;
while (t1.a[t1.len - 1] == 0 && t1.len > 1)
{
t1.len--;
big--;
}
if (flag)
t1.a[big - 1] = 0 - t1.a[big - 1];
return t1;
}
BigNum BigNum::operator*(const BigNum &T) const
{
BigNum ret;
int i, j, up;
int temp, temp1;
for (i = 0; i < len; i++)
{
up = 0;
for (j = 0; j < T.len; j++)
{
temp = a[i] * T.a[j] + ret.a[i + j] + up;
if (temp > MAXN)
{
temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);
up = temp / (MAXN + 1);
ret.a[i + j] = temp1;
}
else
{
up = 0;
ret.a[i + j] = temp;
}
}
if (up != 0)
ret.a[i + j] = up;
}
ret.len = i + j;
while (ret.a[ret.len - 1] == 0 && ret.len > 1)
ret.len--;
return ret;
}
BigNum BigNum::operator/(const int &b) const
{
BigNum ret;
int i, down = 0;
for (i = len - 1; i >= 0; i--)
{
ret.a[i] = (a[i] + down * (MAXN + 1)) / b;
down = a[i] + down * (MAXN + 1) - ret.a[i] * b;
}
ret.len = len;
while (ret.a[ret.len - 1] == 0 && ret.len > 1)
ret.len--;
return ret;
}
int BigNum::operator%(const int &b) const
{
int i, d = 0;
for (i = len - 1; i >= 0; i--)
{
d = ((d * (MAXN + 1)) % b + a[i]) % b;
}
return d;
}
BigNum BigNum::operator^(const int &n) const
{
BigNum t, ret(1);
int i;
if (n < 0)
exit(-1);
if (n == 0)
return 1;
if (n == 1)
return *this;
int m = n;
while (m > 1)
{
t = *this;
for (i = 1; i << 1 <= m; i <<= 1)
{
t = t * t;
}
m -= i;
ret = ret * t;
if (m == 1)
ret = ret * (*this);
}
return ret;
}
bool BigNum::operator>(const BigNum &T) const
{
int ln;
if (len > T.len)
return true;
else if (len == T.len)
{
ln = len - 1;
while (a[ln] == T.a[ln] && ln >= 0)
ln--;
if (ln >= 0 && a[ln] > T.a[ln])
return true;
else
return false;
}
else
return false;
}
bool BigNum::operator>(const int &t) const
{
BigNum b(t);
return *this > b;
}
void BigNum::print()
{
int i;
cout << a[len - 1];
for (i = len - 2; i >= 0; i--)
{
cout.width(DLEN);
cout.fill('0');
cout << a[i];
}
cout << endl;
}
bool BigNum::operator<(const BigNum &obj) const
{
for (int i = 0; i < len; i++)
{
if (a[i] < obj.a[i])
return true;
if (a[i] > obj.a[i])
return false;
}
return false;
}
bool BigNum::operator<=(const BigNum &obj) const
{
for (int i = 0; i < len; i++)
{
if (a[i] < obj.a[i])
return true;
if (a[i] > obj.a[i])
return false;
}
return true;
}
bool BigNum::operator>=(const BigNum &obj) const
{
for (int i = 0; i < len; i++)
{
if (a[i] > obj.a[i])
return true;
if (a[i] < obj.a[i])
return false;
}
return true;
}
bool BigNum::operator==(const BigNum &obj) const
{
for (int i = 0; i < len; i++)
{
if (a[i] != obj.a[i])
return false;
}
return true;
}
bool BigNum::operator!=(const BigNum &obj) const
{
for (int i = 0; i < len; i++)
{
if (a[i] != obj.a[i])
return true;
}
return false;
}
BigNum BigNum::operator/(const BigNum &op2) const
{
BigNum temp(*this);
if (op2 == 0)
{
cout << "ERROR!!";
for (int i = 0; i < len; i++)
temp.a[i] = 0;
}
else if (*this < op2)
{
for (int i = 0; i < len; i++)
temp.a[i] = 0;
}
else if (*this == op2)
{
temp.a[len - 1] = 1;
}
else if (op2 == 1)
{
temp = *this;
}
else if (op2 == 2)
{
int from = 0;
for (int i = 0; i < len; i++)
{
if (temp.a[i] != 0)
{
from = i;
break;
}
}
int carry = 0;
for (int i = from; i < len; i++)
{
if (temp.a[i] & 1)
{
if (carry == 1)
temp.a[i] = (temp.a[i] + 10) / 2;
else
temp.a[i] = temp.a[i] / 2;
carry = 1;
}
else
{
if (carry == 1)
temp.a[i] = (temp.a[i] + 10) / 2;
else
temp.a[i] = temp.a[i] / 2;
carry = 0;
}
}
}
else
{
BigNum begin(1), end("500000000000000000000000000000"); // 500000000000000000000000000000
while (begin < end)
{
BigNum mid = (begin + end) / 2;
BigNum res = mid * op2;
if (res == 0 || res >= *this)
end = mid;
else
begin = mid + 1;
}
temp = begin;
if (temp == 1)
return 0;
int tmp = len - 1;
while (temp.a[tmp] == 0)
{
temp.a[tmp] = 9;
tmp++;
}
temp.a[tmp]--;
return temp;
}
return temp;
}
When I run it, sometimes I get the error "malloc(): corrupted top size", sometimes it will run and then nothing happens, when I debug it, I find that the problem is in the "mygcd" function, the algorithm I use is too slow for a huge The algorithm I'm using is too slow for the huge number, but I don't know how to change it. I'm not sure where in the two files something is going wrong that I don't know about, and I can't guarantee that all the algorithms I'm using are correct and appropriate. Can anyone help me? Thanks a lot.
My system is Ubuntu 22.04.1LTS
gcc version 11.2.0
Now I deleted all the Chinese comments
After applying all of the changes suggested in the comments:
Remove using namespace std;
Remove superfluous BigNum::operator= and BigNum::BigNum(BigNum&)
Only implement fully BigNum::operator< and BigNum::operator==, and the other relational operators are based on those two operators
Make BigNum::operator << have the second argument as a const reference to BigNum.
the compiler here warns of j not being initialized.
BigNum BigNum::operator*(const BigNum &T) const //两个大数之间的相乘运算
{
BigNum ret;
int i, j, up;
//...
ret.len = i + j;
//...
}
You see the results of the run, with the Address Sanitizer showing that things are not working right.
When j is initialized to 0, then the program runs without error, at least the main you provided runs without error.
Edit:
On further inspection, you are accessing arr out-of-bounds. After changing the a to std::array<int, 999> a; and used at() within BigNum::operator *, a std::out_of_range exception is thrown:
Here is the updated code.
Also, please name your variables with meaningful names, not one letter names like a. Naming your variables properly will aid in understanding the code a lot better.
thanks for visiting my question! Currently, when I run this code (an implementation of the Set data structure in c++), the memory address of each element in the set is printed instead of the values in the set. To help with debugging, here's my code:
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cassert>
#define PB push_back
typedef std::vector<int> vint;
class SetBase
{
public:
SetBase() {}
~SetBase() {}
void insert(int x)
{
if (!this->isInSet(x))
{
this->set.PB(x);
}
}
int size()
{
return this->set.size();
}
bool empty()
{
return this->size() == 0;
}
int operator[](int index)
{
if (index >= 0 && index < this->size())
{
return this->set[index];
}
else
{
return -1;
}
}
bool find(int target)
{
sort(this->set.begin(), this->set.end());
int low = 0, high = this->size();
while (low <= high)
{
long long mid = low + (high - low) / 2;
long long guess = this->set[mid];
if (guess == target)
return true;
else if (guess < target)
low = mid + 1;
else
high = mid - 1;
}
return false;
}
int count(int target)
{
int counter = 0;
for (int i = 0; i < this->set.size(); i++)
{
if (this->set[i] == target)
counter++;
}
return counter;
}
bool operator=(SetBase &other)
{
if (other.size() != this->size())
return false;
for (int i = 0; i < other.size(); i++)
{
if (other[i] != this->set[i])
return false;
}
return true;
}
private:
vint set;
bool isInSet(int target)
{
for (int i = 0; i < this->size(); i++)
{
if (set[i] == target)
{
return true;
}
}
return false;
}
};
class Set : public SetBase
{
public:
void set_union(Set *set1, Set *set2, Set &back_insertor)
{
for (int i = 0; i < set1->size(); i++)
{
if (this->isInSet(back_insertor, i))
{
back_insertor.insert(i);
}
}
}
void set_difference(Set set1, Set set2, Set &back_insertor)
{
// set_difference = set1 - set2
}
void set_intersection(Set set1, Set set2, Set &back_insertor)
{
// set_difference = set1 U set2
for (int i = 0; i < set1.size(); i++)
{
for (int j = 0; j < set2.size(); j++)
{
if (set1[i] == set2[j])
{
back_insertor.insert(set1[i]);
}
}
}
}
void printSet(Set *in)
{
for (int i = 0; i < in->size(); i++)
{
std::cout << &in[i] << "\n";
}
}
private:
bool isInSet(SetBase set1, int target)
{
for (int i = 0; i < set1.size(); i++)
{
if (target == set1[i])
{
return true;
}
}
return false;
}
};
int main()
{
Set *set_1 = new Set();
Set *set_2 = new Set();
Set *back = new Set();
for (int i = 1; i <= 10; i++)
set_1->insert(i);
for (int i = 1; i <= 10; i++)
set_2->insert(i);
set_2->insert(11);
set_1->set_union(set_1, set_2, *back);
set_1->printSet(set_1);
delete set_1;
delete set_2;
delete back;
}
When running the set_1->printSet(set_1); line, here's what I get:
0x7fb498c05a20
0x7fb498c05a38
0x7fb498c05a50
0x7fb498c05a68
0x7fb498c05a80
0x7fb498c05a98
0x7fb498c05ab0
0x7fb498c05ac8
0x7fb498c05ae0
0x7fb498c05af8
Even though this works, I would like to print out the values (integer) instead. Any help would be appreciated! Thanks! :)
Inside printSet(), you use &in[i] to print each element.
The & operator returns the address of the object you are referencing. So, instead of getting the value, you are getting its address. You should remove it, eg:
void printSet(Set *in)
{
for (int i = 0; i < in->size(); i++)
{
std::cout << (*in)[i] << "\n";
}
}
This is a project for my object oriented programming class. I need to introduce the followings: overloading + to sum two polynomials, overloading * to multiply a polynomial with a scalar or to multiply it with another polynomial, overloading [] to return coeficient on a specific position, method for adding , deleting a coeficient and evaluating polynom in a certain point (f(x)).
1.Everything is working besides the destructor. The destructor that should be used (delete [] coef) of Polynomial will break (Heap Coruption) if i use cout << A + B and i do not know why.
What i use right now is a workaround but it will not delete coef[0]. That's the point where it breaks. If you can help me somehow i will be gratefull. Can you understand what caused it?
2.I need to have one more overloaded operator, " / ". It should make division between two polynomials and I do not know how to implement it. I tried to search for it but i couldn't understand any algorithm. Any advice or algorithm explanation would be great, because i really do not know from where to start and i need to finish it until tommorrow morning.
3.If you have any advice on coding or efficienty will also be great ( project requirement: do not use STL ).
Thank you!
Polynomial.h:
#pragma once
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
using std::ostream;
using std::istream;
class Polynomial
{
unsigned int deg;
double *coef;
public:
Polynomial() : deg(1), coef(new double[1]) {}
Polynomial(double [], int);
Polynomial(Polynomial&);
Polynomial& operator = (const Polynomial&);
~Polynomial();
friend ostream &operator <<(ostream&, const Polynomial&);
friend istream &operator >>(istream&, Polynomial&);
Polynomial operator + (const Polynomial) ;
double operator[] (unsigned int) const;
Polynomial operator * (int) const;
Polynomial operator * (const Polynomial obj) const;
unsigned int getDeg() { return this->deg; };
double eval(int);
void addCoef(double, int);
void delCoef(int);
};
inline Polynomial::Polynomial(double coefficients[], int number) : deg(number), coef(new double[number])
{
for (int i = 0; i < deg; i++) {
coef[i] = coefficients[i];
}
}
inline Polynomial::Polynomial(Polynomial &ob) {
this->deg = ob.deg;
this->coef = new double[deg];
for (int i = 0; i <= deg; i++)
{
this->coef[i] = ob.coef[i];
}
}
inline Polynomial::~Polynomial() {
for (int i = this->deg; i > 0; i--)
this->delCoef(i);
this->coef[0] = 0; //If i write it like this delete [] coef; it breaks.
this->deg = 0; //with HeapCoruption detected
}
Polynomial.cpp:
Polynomial& Polynomial::operator = (const Polynomial& obj)
{
if (this != &obj) //Testing to avoid situations like A = A;
{
this->deg = obj.deg;
for (int i = 0; i <= obj.deg; i++)
this->coef[i] = obj.coef[i];
}
return *this;
}
istream& operator >> (istream& in, Polynomial& obj)
{
in >> obj.deg;
cout << endl;
obj.coef = new double[obj.deg];
for (int i = 0; i <= obj.deg; i++)
{
in >> obj.coef[i];
}
return in;
}
ostream& operator << (ostream& out, const Polynomial& obj)
{
out << obj.deg << endl;
for (int i = 0; i <= obj.deg; i++)
{
if (obj.coef[i] != 0)
{
if (obj.coef[i] < 0)
out << '(' << obj.coef[i] << ')';
else
out << obj.coef[i];
if (i > 1)
out << "*x^" << i;
if (i == 1)
out << "*x";
if (i != obj.deg)
out << " + ";
}
}
out << endl <<endl;
return out;
}
Polynomial Polynomial::operator+ (const Polynomial obj)
{
Polynomial aux;
if (obj.deg >= deg)
{
aux.deg = obj.deg;
aux.coef = new double[obj.deg];
for (int i = 0; i <= deg; i++)
aux.coef[i] = obj.coef[i] + coef[i];
for (int i = deg + 1; i <= obj.deg; i++)
aux.coef[i] = obj.coef[i];
}
else // obj.deg < this->deg
{
aux.deg = deg;
aux.coef = new double[deg];
for (int i = 0; i <= obj.deg; i++)
{
aux.coef[i] = obj.coef[i] + coef[i];
}
for (int i = obj.deg + 1; i <= deg; i++)
{
aux.coef[i] = coef[i];
}
}
return aux;
}
double Polynomial::operator[] (unsigned int pos) const
{
if (pos > this->deg) {
throw std::out_of_range("Index bigger than polynomial length");
}
return this->coef[pos];
}
Polynomial Polynomial::operator * (const int scalar) const
{
Polynomial aux;
aux.deg = this->deg;
aux.coef = new double[aux.deg];
for (int i = 0; i <= aux.deg; i++)
aux.coef[i] = this->coef[i] * scalar;
return aux;
}
Polynomial Polynomial::operator * (const Polynomial obj) const
{
Polynomial aux;
aux.deg = obj.deg + this->deg;
aux.coef = new double[aux.getDeg()];
for (int i = 0; i <= aux.getDeg(); i++)
aux.addCoef(0, i);
for (int i = 0; i <= this->deg; i++)
for (int j = 0; j <= obj.deg; j++)
aux.coef[i+j] += (this->coef[i]) * obj.coef[j];
return aux;
}
double Polynomial::eval(int x) {
double sum = 0;
for (int i = 0; i <= this->deg; i++)
{
if (i == 0)
sum += this->coef[0];
else
{
int aux = i;
int xaux = x;
aux--;
while (aux != 0)
{
xaux *= x;
aux--;
}
sum += this->coef[i] * xaux;
}
}
return sum;
}
void Polynomial::addCoef(double NewCoef, int pos)
{
if (pos < 0)
return;
if (pos > this->deg)
{
double *newCoef = new double[pos];
for (int i = 0; i <= this->deg; i++)
newCoef[i] = this->coef[i];
for (int i = this->deg + 1; i < pos; i++)
newCoef[i] = 0;
newCoef[pos] = NewCoef;
this->coef = newCoef;
this->deg = pos;
return;
}
else
{
this->coef[pos] = NewCoef;
}
}
void Polynomial::delCoef(int pos)
{
if (pos > this->deg || pos < 0 )
return;
if (pos == this->deg)
{
this->coef[pos] = 0;
int degNoua = pos - 1;
while (this->coef[pos] == 0 && pos != 0)
pos--;
if (pos == 0 && this->coef[pos] == 0)
{
delete this->coef;
this->deg = 0;
}
else
{
this->deg = pos;
double *aux = new double[pos];
for (int i = 0; i <= pos; i++)
aux[i] = this->coef[i];
this->coef = aux;
}
}
else
{
this->coef[pos] = 0;
}
}
I already managed to implement most of what I planned to do correctly, but somehow I struggle with the unique and cut method.
The unique method should sort the vector and delete all entries that appear more than once and the original vector should be overwritten with the shortened on. The cut method should delete all entries < cMin or > cMax.
Here is my try so far:
#include <cassert>
#include <iostream>
using std::cout;
using std::endl;
class Vector {
private:
int n;
double* coeff;
public:
Vector(int, double = 0);
~Vector();
Vector(const Vector&);
Vector& operator=(const Vector&);
int size() const;
double& operator()(int);
const double& operator()(int) const;
double max() const;
void sort();
void unique();
void cut(double Cmin, double Cmax);
void print() const;
};
Vector::Vector(int n, double init)
{
assert(n >= 0);
this->n = n;
if (n == 0) {
coeff = (double*)0;
}
else {
coeff = new double[n];
}
for (int i = 0; i < n; i++) {
coeff[i] = init;
}
}
Vector::Vector(const Vector& rhs)
{
n = rhs.n;
if (n > 0) {
coeff = new double[n];
}
else {
coeff = (double*)0;
}
for (int i = 0; i < n; i++) {
coeff[i] = rhs.coeff[i];
}
}
Vector::~Vector()
{
if (n > 0) {
delete[] coeff;
}
}
Vector& Vector::operator=(const Vector& rhs)
{
if (this != &rhs) {
if (n != rhs.n) {
if (n > 0) {
delete[] coeff;
}
n = rhs.n;
if (n > 0) {
coeff = new double[n];
}
else {
coeff = (double*)0;
}
}
for (int i = 0; i < n; i++) {
coeff[i] = rhs.coeff[i];
}
}
return *this;
}
int Vector::size() const
{
return n;
}
double& Vector::operator()(int j)
{
assert(j >= 1 && j <= n);
return coeff[j - 1];
}
const double& Vector::operator()(int j) const
{
assert(j >= 1 && j <= n);
return coeff[j - 1];
}
double Vector::max() const
{
double max = coeff[0];
for (int i = 1; i < n; i++) {
if (coeff[i] > max) {
max = coeff[i];
}
}
return max;
}
void Vector::sort()
{ //bubble-sort
double tmp = 0;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1; j++) {
if (coeff[j] > coeff[j + 1]) {
tmp = coeff[j];
coeff[j] = coeff[j + 1];
coeff[j + 1] = tmp;
}
}
}
}
void Vector::unique()
{
sort();
int counter = 0;
Vector kopie = *this;
for (int i = 0; i < n; i++) {
if (i == 0 && coeff[i] != coeff[i + 1]) {
counter++;
}
if (i == n - 1 && coeff[i] != coeff[i - 1]) {
counter++;
}
if (i != 0 && i != n - 1 && coeff[i] != coeff[i - 1] && coeff[i] != coeff[i + 1]) {
counter++;
}
}
delete[] coeff;
coeff = new double[counter];
//to be continued...
}
void Vector::cut(double Cmin, double Cmax)
{
sort();
int counter = 0;
int j = 0;
Vector kopie = *this;
for (int i = 0; i < n; i++) {
if (coeff[i] >= Cmin && coeff[i] <= Cmax) {
counter++;
}
}
delete[] coeff;
coeff = new double[counter];
for (int i = 0; i < n; i++) {
if (kopie.coeff[i] >= Cmin && kopie.coeff[i] <= Cmax) {
coeff[j] = kopie.coeff[i];
j++;
if (j == n) {
break;
}
}
}
}
void Vector::print() const
{
for (int i = 0; i < n; i++) {
cout << coeff[i] << " ";
}
}
int main()
{
Vector X(8);
X.print();
cout << endl;
X(1) = 1.;
X(2) = 7.;
X(3) = 2.;
X(4) = 5.;
X(5) = 6.;
X(6) = 5.;
X(7) = 9.;
X(8) = 6.;
X.print();
cout << endl;
X.sort();
X.print();
cout << endl;
//X.unique();
//X.print();
//cout << endl;
X.cut(2, 6);
X.print();
cout << endl;
return 0;
}
For the unique function, rather than checking if it's legal to move the counter forward, I would just check if your current element and the next element aren't the same. If they are, set the next element's pointer to skip over the duplicate element.
Pseduocode:
For(int i = 0; i < n-1; i++) {
if(coef[i] == coef[i+1]) {
//Keep moving next element pointer until not equal. Probably use a while loop
}
}
The simplest solution that I can think of is something like this:
void Vector::unique()
{
size_t counter = 0;
double* copy = new double[n];
copy[counter++] = coeff[0]; // The first element is guaranteed to be unique
// Since coeff is sorted, copy will be sorted as well.
// Therefore, its enough to check only the last element of copy to
// the current element of coeff
for (size_t i = 1; i < n; i++)
{
if (coeff[i] != copy[counter])
{
copy[counter++] = coeff[i];
}
}
// copy already contains the data in the format that you want,
// but the reserved memory size may be larger than necessary.
// Reserve the correct amount of memory and copy the data there
delete[] coeff;
coeff = new double[counter];
std::memcpy(coeff, copy, counter*sizeof(double));
}
For cut() you can use a similar algorithm:
void Vector::cut(double Cmin, double Cmax)
{
size_t counter = 0;
double* copy = new double[n];
for (size_t i = 0; i < n; i++)
{
if (coeff[i] > Cmin && coeff[i] < Cmax)
{
copy[counter++] = coeff[i];
}
}
// Same story with memory size here as well
delete[] coeff;
coeff = new double[counter];
std::memcpy(coeff, copy, counter*sizeof(double));
}
Is there any reason why you can't use the standard library?
void Vector::unique() {
std::sort(coeff, std::next(coeff, n));
auto it = std::unique(coeff, std::next(coeff, n));
double* tmp = new double[n = std::distance(coeff, it)];
std::copy(coeff, it, tmp);
delete[] std::exchange(coeff, tmp);
}
void Vector::cut(double Cmin, double Cmax) {
auto it = std::remove_if(coeff, std::next(coeff, n),
[=] (double d) { return d < Cmin || d > Cmax; });
double* tmp = new double[n = std::distance(coeff, it)];
std::copy(coeff, it, tmp);
delete[] std::exchange(coeff, tmp);
}
To remove duplicates and sort, you can achieve it in three ways
Just using vector, sort + unique
sort( vec.begin(), vec.end() );
vec.erase( unique( vec.begin(), vec.end() ), vec.end() );
Convert to set (manually)
set<int> s;
unsigned size = vec.size();
for( unsigned i = 0; i < size; ++i )
s.insert( vec[i] ); vec.assign( s.begin(), s.end() );
Convert to set (using a constructor)
set<int> s( vec.begin(), vec.end() );
vec.assign( s.begin(), s.end() );
All three has different performance. You can use one depending upon your size and number of duplicates present.
To cut you can use algorithm library
std::remove, std::remove_if
Syntax
template< class ForwardIt, class T >
constexpr ForwardIt remove( ForwardIt first, ForwardIt last, const T& value );
Possible implementation
First version
template< class ForwardIt, class T > ForwardIt remove(ForwardIt first, ForwardIt last, const T& value)
{ first = std::find(first, last, value);
if (first != last)
for(ForwardIt i = first; ++i != last; )
if (!(*i == value))
*first++ = std::move(*i); return first; }
Second version
template<class ForwardIt, class UnaryPredicate> ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate p)
{ first = std::find_if(first, last, p);
if (first != last)
for(ForwardIt i = first; ++i != last; )
if (!p(*i)) *first++ = std::move(*i);
return first; }
Examples
The following code removes all spaces from a string by shifting all non-space characters to the left and then erasing the extra. This is an example of erase-remove idiom.
Run this code
#include <algorithm>
#include <string>
#include <iostream>
#include <cctype>
int main()
{ std::string str1 = "Text with some spaces"; str1.erase(std::remove(str1.begin(), str1.end(), ' '), str1.end());
std::cout << str1 << '\n';
std::string str2 = "Text\n with\tsome \t whitespaces\n\n"; str2.erase(std::remove_if(str2.begin(), str2.end(), [](unsigned char x)
{return std::isspace(x);}), str2.end());
std::cout << str2 << '\n'; }
Output:
Textwithsomespaces
Textwithsomewhitespaces
This is pacific question. The implementation of the class LargeInt will use a dynamic physical structure to store the individual digits of an integer, and will provide some basic I/O and arithmetic operations that can be performed on integers.
In particular, the class should include:
A default constructor
An operator function to overload the operator +
An operator function to overload the operator ==
An operator function to overload the operator <<
An operator function to overload the operator >>
Note 1: since the LargeInt class does not contain pointers, there is no need for a copy constructor or a destructor.
#include "targetver.h"
using namespace std;
class LargeInt
{
private:
char datain[200];
int databit[200];
int len;
int overflow;
LargeInt(char *x, int inlen)
{
int i = 0;
int j = inlen - 1;
len = inlen;
overflow = 0;
for (i = 0; i < 200; i++)
{
databit[i] = 0;
datain[i] = '\0';
}
for (i = 0; i < len; i++)
{
datain[i] = x[j];
j--;
}
}
~LargeInt();
void GetDataBit()
{
int i = 0;
for (i; i < len; i++)
databit[i] = datain[i] - 48;
}
public:
LargeInt& operator+(LargeInt& data);
bool operator==(LargeInt& data);
LargeInt& operator>>(int x);
LargeInt& operator<<(int x);
};
bool LargeInt::operator==(LargeInt& data)
{
if (this->len != data.len)
return false;
else
{
for (int i = 0; i < 200; i++)
{
if (this->databit[i] == data.databit[i])
continue;
else
return false;
}
return true;
}
}
LargeInt& LargeInt::operator+(LargeInt& data)
{
LargeInt t("0", 0);
int addlen;
if (this->len > data.len)
addlen = this->len;
else
addlen = data.len;
for (int i = 0; i < addlen; i--)
{
t.databit[i] = (data.databit[i] + this->databit[i] + t.overflow) % 10;
if ((data.databit[i] + this->databit[i] + t.overflow) >= 10)
t.overflow = 1;
}
t.len = addlen;
for (int i = 0; i < addlen; i++)
{
t.datain[i] = t.databit[i] + 48;
}
return t;
}
when I build it, it has a error like this
Warning 1 warning C4172: returning address of local variable or temporary.
LargeInt& LargeInt::operator+(LargeInt& data)
remove the & and your warning should go away. Right now the return is referencing a variable t, which is local to the function which has gone out of scope by the time the calling function catches the return.