-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Division operation #18
base: master
Are you sure you want to change the base?
Changes from 5 commits
3688793
7846e33
5f160ac
7e9d1ca
30f3714
85adfe0
35a3976
f8cb53c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,9 @@ | |
#include <sstream> | ||
#include <map> | ||
#include "bigint.h" | ||
#include <cmath> | ||
#include <stdlib.h> | ||
#include <exception> | ||
|
||
namespace Dodecahedron | ||
{ | ||
|
@@ -118,7 +121,9 @@ Bigint &Bigint::operator+=(long long b) | |
number.insert(number.end(), skip - number.size(), 0); | ||
} | ||
it += skip; | ||
while (b) { | ||
bool initial_flag=true; | ||
while (b || initial_flag) { | ||
initial_flag=false; | ||
if (it != number.end()) { | ||
*it += b % base; | ||
b /= base; | ||
|
@@ -188,7 +193,7 @@ Bigint Bigint::operator*(Bigint const &b) | |
if (b.number.size() == 1) return *this *= b.number[0]; | ||
std::vector<int>::iterator it1; | ||
std::vector<int>::const_iterator it2; | ||
Bigint c; | ||
Bigint c("0"); | ||
for (it1 = number.begin(); it1 != number.end(); ++it1) { | ||
for (it2 = b.number.begin(); it2 != b.number.end(); ++it2) { | ||
c.skip = (unsigned int) (it1 - number.begin()) + (it2 - b.number.begin()); //TODO | ||
|
@@ -230,7 +235,201 @@ Bigint &Bigint::operator*=(int const &b) | |
return *this; | ||
} | ||
|
||
bool Bigint::is_even(){ | ||
if(number.size()==1){ | ||
int x = number[0]; | ||
if(x%2 == 0) | ||
return true; | ||
else | ||
return false; | ||
} | ||
|
||
else if(number.size()>1){ | ||
int x = *(number.begin()); | ||
if(x%2 == 0) | ||
return true; | ||
else | ||
return false; | ||
} | ||
|
||
} | ||
|
||
|
||
Bigint Bigint::sub_number(Bigint &p, Bigint &q){ | ||
|
||
std::string tmpx0, tmpx1, tmpx3; | ||
long window_size = q.digits(); | ||
int last_i_iterator; | ||
std::vector<int>::iterator i=p.number.end()-1; | ||
|
||
if(window_size>p.digits()) | ||
window_size=p.digits(); | ||
|
||
|
||
while(i>=p.number.begin() && window_size>0){ | ||
|
||
tmpx0 = to_string(*i); | ||
int ssss = tmpx0.size(); | ||
if(i!=p.number.end()-1 && ssss<9){ | ||
tmpx0 = std::string(9-ssss,'0') + tmpx0; | ||
} | ||
|
||
if(window_size - ssss < 0){ | ||
tmpx3=tmpx0; | ||
tmpx0=""; | ||
for(int i=0;i<window_size;i++){ | ||
tmpx0=tmpx0+tmpx3[i]; | ||
last_i_iterator=i; | ||
} | ||
window_size = window_size - tmpx0.size(); | ||
tmpx1 = tmpx1 + tmpx0; | ||
} | ||
else{ | ||
window_size = window_size - tmpx0.size(); | ||
tmpx1 = tmpx1 + tmpx0; | ||
i--; | ||
} | ||
} | ||
|
||
Bigint c(tmpx1); | ||
|
||
if(c<q && i>=p.number.begin()){ | ||
if(tmpx3.size()!=0){ | ||
window_size++; | ||
tmpx0 = tmpx3[last_i_iterator+1]; | ||
tmpx1 = tmpx1 + tmpx0; | ||
c=tmpx1; | ||
} | ||
else{ | ||
window_size++; | ||
tmpx0 = to_string(*i); | ||
if(i!=p.number.end()-1 && tmpx0.size()<9){ | ||
tmpx0 = std::string(9-tmpx0.size(),'0') + tmpx0; | ||
} | ||
tmpx0 = tmpx0[0]; | ||
tmpx1 = tmpx1 + tmpx0; | ||
c=tmpx1; | ||
} | ||
|
||
} | ||
|
||
return c; | ||
} | ||
//Division | ||
|
||
std::vector<Bigint> Bigint::divide(Bigint q){ | ||
|
||
/*Algorithm used is "Double division algorithm"*/ | ||
|
||
Bigint p = *this; | ||
std::vector<Bigint> answer; | ||
int look_up_table_size=4; | ||
std::vector<Bigint> look_up(look_up_table_size); | ||
bool done_flag=false ; | ||
Bigint tmp_quotient, sum_quotient, tmpx1, tmpx2; | ||
|
||
Bigint zero("0"); | ||
|
||
if(q==zero || q == 0){ | ||
//std::cout << "Error: Dividing by zero" << std::endl; | ||
//exit (EXIT_FAILURE); | ||
throw "Dividing by zero!"; | ||
} | ||
|
||
bool this_sign = this -> positive; | ||
bool q_sign = q.positive; | ||
|
||
p.positive = true; | ||
q.positive = true; | ||
|
||
|
||
look_up[0]=q; | ||
look_up[1]=q*2; | ||
look_up[2]=q*4; | ||
look_up[3]=q*8; | ||
|
||
|
||
while(true){ | ||
|
||
Bigint sub_p=sub_number(p, q); // cut a portion from the dividened equal in size with the divisor | ||
|
||
for(int i=0;i<look_up_table_size;i++){ // looking in the look_up table | ||
|
||
if(sub_p<look_up[i] && i!=0){ | ||
tmpx1=look_up[i-1]; | ||
tmp_quotient = std::pow(2,i-1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe |
||
break; | ||
} | ||
else if(sub_p<look_up[i] && i==0){ | ||
|
||
if(q.digits()>=p.digits()){ | ||
done_flag=true; | ||
break; | ||
} | ||
} | ||
else if(sub_p==look_up[i] || (sub_p>look_up[i] && i==look_up_table_size-1)){ | ||
tmpx1=look_up[i]; | ||
tmp_quotient= std::pow(2,i); | ||
break; | ||
} | ||
} | ||
|
||
if(done_flag){ | ||
answer.push_back(sum_quotient); | ||
answer.push_back(sub_p); | ||
break; | ||
} | ||
|
||
std::string temppp(p.digits()-(sub_p.digits()),'0'); | ||
temppp="1"+temppp; | ||
tmpx2=temppp; | ||
|
||
if(sum_quotient.digits()==0) | ||
sum_quotient=tmp_quotient*tmpx2; | ||
else | ||
sum_quotient=sum_quotient+(tmp_quotient*tmpx2); | ||
|
||
tmpx1=tmpx1*tmpx2; | ||
p=p-tmpx1; | ||
|
||
} | ||
|
||
if(this_sign == false && q_sign == false){ | ||
answer[0].positive = true; | ||
} | ||
|
||
else if(this_sign == false || q_sign == false){ | ||
if( this -> is_even() && q.is_even()) | ||
answer[0].positive = false; | ||
else{ | ||
answer[0] = answer[0] + Bigint("1"); | ||
answer[0].positive = false; | ||
} | ||
} | ||
|
||
else{ | ||
answer[0].positive = true; | ||
} | ||
|
||
return answer; | ||
|
||
} | ||
|
||
std::vector<Bigint> Bigint::operator/(Bigint q){ | ||
try{ | ||
return divide(q); | ||
} | ||
catch(const char* msg){ | ||
std::cerr << msg << std::endl; | ||
std::terminate(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If an exception is thrown, is it user catchable? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no, user won't catch it. It is caught in the division function interface only and printed on screen as shown above. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Throwing the error is enough, you dont have to catch it. If division by zero occurs, let the user deal with it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My solution is to make an inheriting class to void check_divisor(Bigint const &b)
{
if (b == 0)
throw Bigint::arithmetic_error("Divide by zero");
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @titansnow I agree. That would be better. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, i will try it. |
||
} | ||
|
||
|
||
} | ||
|
||
|
||
//Power | ||
|
||
Bigint Bigint::pow(int const &power, std::map<int, Bigint> &lookup) | ||
{ | ||
if (power == 1) return *this; | ||
|
@@ -392,6 +591,7 @@ std::ostream &operator<<(std::ostream &out, Bigint a) | |
return out; | ||
} | ||
|
||
|
||
std::istream &operator>>(std::istream &in, Bigint &a) | ||
{ | ||
std::string str; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,6 +38,12 @@ class Bigint | |
Bigint operator*(long long const &); | ||
Bigint &operator*=(int const &); | ||
|
||
//Division | ||
bool is_even(); | ||
private: | ||
std::vector<Bigint> divide(Bigint q); // returns quotient(index[0]) and remainder(index[1]). | ||
public: | ||
std::vector<Bigint> operator/(Bigint q); // interface for divide() function. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does division return a vector? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. because it returns both quotient and remainder. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. divide() can stay as is, but There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there can be both There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes make it two separate operators. Also, could you also describe how the algorithm works and why it works? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, i will separate it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the link. That is an awesome algorithm indeed. |
||
//Compare | ||
bool operator<(const Bigint &) const; | ||
bool operator>(const Bigint &) const; | ||
|
@@ -69,6 +75,7 @@ class Bigint | |
int segment_length(int) const; | ||
Bigint pow(int const &, std::map<int, Bigint> &); | ||
int compare(Bigint const &) const; //0 a == b, -1 a < b, 1 a > b | ||
Bigint sub_number(Bigint &p, Bigint &q); // used in the division function | ||
}; | ||
|
||
Bigint abs(Bigint); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the commented out code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i will fix it.