Last active
December 18, 2015 03:39
-
-
Save shukob/5719839 to your computer and use it in GitHub Desktop.
C++: Simple 1d equation solver
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdio> | |
#include <string> | |
#include <sstream> | |
template<typename T> | |
class Fraction{ | |
public: | |
typedef T number_type; | |
Fraction(): | |
_numerator(0), | |
_denominator(0), | |
_requiresStringification(false), | |
_stringified(){ | |
} | |
Fraction(T numerator, T denominator = 1): | |
_numerator(numerator), | |
_denominator(denominator), | |
_requiresStringification(true), | |
_stringified(){ | |
reduce(); | |
} | |
std::string to_s(){ | |
if(_requiresStringification){ | |
stringify(); | |
_requiresStringification = false; | |
} | |
return _stringified; | |
} | |
void setNumerator(T numerator){ | |
_numerator = numerator; | |
_requiresStringification = true; | |
reduce(); | |
} | |
void setDenominator(T denominator){ | |
_denominator = denominator; | |
_requiresStringification = true; | |
reduce(); | |
} | |
protected: | |
T _numerator; | |
T _denominator; | |
bool _requiresStringification; | |
std::string _stringified; | |
void reduce(){ | |
//transit sign to the numerator | |
if(_denominator * _numerator < 0){ | |
_numerator = -abs(_numerator); | |
_denominator = abs(_denominator); | |
}else{ | |
_numerator = abs(_numerator); | |
_denominator = abs(_denominator); | |
} | |
if(_numerator==0 || _denominator==1){ //no needs for reduction | |
return; | |
}else if(_denominator ==0){//this is nan | |
return; | |
}else{//reduce | |
T _gcd = gcd(abs(_numerator), abs(_denominator)); | |
_numerator /= _gcd; | |
_denominator /= _gcd; | |
} | |
} | |
void stringify(){ | |
std::ostringstream ost; | |
if(_denominator==1){ | |
ost << _numerator; | |
}else if(_denominator==0){ | |
ost << "NaN"; | |
}else{ | |
ost << _numerator << "/" << _denominator; | |
} | |
_stringified = ost.str(); | |
} | |
//Taken from https://en.wikipedia.org/wiki/Binary_GCD_algorithm | |
static T gcd(T u, T v) | |
{ | |
// simple cases (termination) | |
if (u == v) | |
return u; | |
if (u == 0) | |
return v; | |
if (v == 0) | |
return u; | |
// look for factors of 2 | |
if (~u & 1) // u is even | |
if (v & 1) // v is odd | |
return gcd(u >> 1, v); | |
else // both u and v are even | |
return gcd(u >> 1, v >> 1) << 1; | |
if (~v & 1) // u is odd, v is even | |
return gcd(u, v >> 1); | |
// reduce larger argument | |
if (u > v) | |
return gcd((u - v) >> 1, v); | |
return gcd((v - u) >> 1, u); | |
} | |
}; | |
//Solve ax + b = cx + d | |
static std::string solve(int a, int b, int c, int d){ | |
if(a==0 && c!=0){ | |
Fraction<int> frac(b-d, c); | |
return "x = " + frac.to_s(); | |
}else if(a!=0 && c==0){ | |
Fraction<int> frac(d-b, a); | |
return "x = " + frac.to_s(); | |
}else if(a==0 && c ==0){ | |
return "impossible"; | |
}else if(a == c){ | |
return "impossible"; | |
}else{ | |
Fraction<int> frac(b - d, c - a); | |
return "x = " + frac.to_s(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment