-
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 all 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 | ||
{ | ||
|
@@ -116,7 +119,10 @@ Bigint &Bigint::operator+=(long long b) | |
} | ||
it += skip; | ||
bool initial_flag=true; | ||
|
||
|
||
while (b || initial_flag) { | ||
|
||
initial_flag=false; | ||
if (it != number.end()) { | ||
*it += b % base; | ||
|
@@ -187,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 | ||
|
@@ -229,7 +235,194 @@ 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){ | ||
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); | ||
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){ | ||
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; | ||
|
@@ -397,6 +590,7 @@ std::ostream &operator<<(std::ostream &out, Bigint const &a) | |
return out; | ||
} | ||
|
||
|
||
std::istream &operator>>(std::istream &in, Bigint &a) | ||
{ | ||
std::string str; | ||
|
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.
Maybe
1<<(i-1)
is an easier and faster choice.pow
incmath
is for float number