public static void Main(){
BigFraction f1 = (BigFraction) n;
Console.WriteLine($"{n} n");
Console.WriteLine($"{f1} {f1.decimalForm} f1\n");
BigFraction f2 = f1.LimitDenominator(128);
Console.WriteLine(BDMath.Exp(z));
Console.WriteLine((BigDecimal) f2);
Console.WriteLine(z * z * z);
private BigInteger Value;
private static int PRECISION_DISPLAY = 25;
private static int PRECISION = PRECISION_DISPLAY + 30;
public static BigInteger DecimalVal = 1;
private static bool decimalValCalculated = false;
public static BigDecimal PI;
private BigDecimal(BigInteger num){
Value = num * DecimalVal;
private BigDecimal(int num){
Value = num * DecimalVal;
private BigDecimal(long num){
Value = num * DecimalVal;
private BigDecimal(BigInteger num, Boolean isShifted){
private BigDecimal(double num){
BigInteger result = (int)(num);
double remainder = num % 1;
for(int a = 0; a < PRECISION; a++){
Value += (int)(remainder);
public static implicit operator BigDecimal(BigInteger num) => new BigDecimal(num);
public static implicit operator BigDecimal(double num) => new BigDecimal(num);
public static implicit operator BigDecimal(long num) => new BigDecimal(num);
public static implicit operator BigDecimal(int num) => new BigDecimal(num);
public static explicit operator BigInteger(BigDecimal num) => num.Value / DecimalVal;
public static BigDecimal operator +(BigDecimal n1, BigDecimal n2) => new BigDecimal(n1.Value + n2.Value, true);
public static BigDecimal operator +(BigDecimal n1) => new BigDecimal(n1.Value, true);
public static BigDecimal operator ++(BigDecimal n1) => new BigDecimal(n1.Value + DecimalVal, true);
public static BigDecimal operator -(BigDecimal n1, BigDecimal n2) => new BigDecimal(n1.Value - n2.Value, true);
public static BigDecimal operator -(BigDecimal n1) => new BigDecimal(-n1.Value, true);
public static BigDecimal operator --(BigDecimal n1) => new BigDecimal(n1.Value - DecimalVal, true);
public static BigDecimal operator *(BigDecimal n1, BigDecimal n2) => new BigDecimal((n1.Value * n2.Value) / DecimalVal, true);
public static BigDecimal operator /(BigDecimal n1, BigDecimal n2) => new BigDecimal((DecimalVal * n1.Value) / n2.Value, true);
public static BigDecimal operator %(BigDecimal n1, BigDecimal n2) => new BigDecimal(n1.Value % n2.Value, true);
public static bool operator ==(BigDecimal n1, BigDecimal n2) => n1.Value == n2.Value;
public static bool operator !=(BigDecimal n1, BigDecimal n2) => n1.Value != n2.Value;
public static bool operator >(BigDecimal n1, BigDecimal n2) => n1.Value > n2.Value;
public static bool operator <(BigDecimal n1, BigDecimal n2) => n1.Value < n2.Value;
public static bool operator >=(BigDecimal n1, BigDecimal n2) => n1.Value >= n2.Value;
public static bool operator <=(BigDecimal n1, BigDecimal n2) => n1.Value <= n2.Value;
public static BigDecimal Abs(BigDecimal num) => num < 0 ? -num : num;
public static BigInteger Abs(BigInteger num) => num < 0 ? -num : num;
public static BigInteger Round(BigDecimal num) => num.Value / DecimalVal;
private static void setDecimalVal(){
if(!decimalValCalculated){
for(int a = 0; a < PRECISION; a++){
decimalValCalculated = true;
public override string ToString(){
BigInteger quotient = Value / DecimalVal;
BigInteger remainder = Abs(Value % DecimalVal);
int digits_remaining = PRECISION_DISPLAY;
while(remainder != 0 && digits_remaining > 0){
BigInteger d = remainder / DecimalVal;
String result = $"{quotient}";
if(!decimalPart.Equals("")){
result += $".{decimalPart}";
public class BigFraction{
public readonly BigInteger num;
public readonly BigInteger den;
public BigFraction(BigInteger num, BigInteger den){
(this.num, this.den) = (-this.num, -this.den);
throw new DivideByZeroException("Denominator can't be 0");
BigInteger commonFactor = GCD(num, den);
this.num /= commonFactor;
this.den /= commonFactor;
public static implicit operator BigFraction(int num) => new BigFraction(num, 1);
public static implicit operator BigFraction(BigInteger num) => new BigFraction(num, 1);
public static explicit operator BigInteger(BigFraction a) => a.num / a.den;
public static explicit operator BigDecimal(BigFraction a) => ((BigDecimal) a.num) / a.den;
public static explicit operator float(BigFraction a) => ((float) a.num) / ((float) a.den);
public static explicit operator double(BigFraction a) => ((double) a.num) / ((double) a.den);
public static explicit operator BigFraction(BigDecimal num){
BigInteger aN = (BigInteger) n;
BigInteger fractionTop = 0;
BigInteger fractionTopN1 = 1;
BigInteger fractionTopN2 = 1;
BigInteger fractionBot = 1;
BigInteger fractionBotN1 = 0;
BigInteger fractionBotN2 = 0;
BigInteger denominatorLimit = BDMath.Pow(2, 48);
BigInteger convergentLimit = BDMath.Pow(2, 30);
BigInteger intPart = (BigInteger) n;
for(int a = 0; a < 10000; a++){
fractionTopN2 = fractionTopN1;
fractionTopN1 = fractionTop;
fractionTop = aN * fractionTopN1 + fractionTopN2;
fractionBotN2 = fractionBotN1;
fractionBotN1 = fractionBot;
fractionBot = aN * fractionBotN1 + fractionBotN2;
if(fractionBot > denominatorLimit || aN > convergentLimit){
fractionTop = fractionTopN1;
fractionBot = fractionBotN1;
return new BigFraction(fractionTop + intPart * fractionBot, fractionBot);
public static BigFraction operator +(BigFraction a, BigFraction b) => new BigFraction(a.num * b.den + a.den * b.num, a.den * b.den);
public static BigFraction operator +(BigFraction a) => a;
public static BigFraction operator ++(BigFraction a) => new BigFraction(a.num + a.den, a.den);
public static BigFraction operator -(BigFraction a, BigFraction b) => new BigFraction(a.num * b.den - a.den * b.num, a.den * b.den);
public static BigFraction operator -(BigFraction a) => new BigFraction(-a.num, -a.den);
public static BigFraction operator --(BigFraction a) => new BigFraction(a.num - a.den, a.den);
public static BigFraction operator *(BigFraction a, BigFraction b) => new BigFraction(a.num * b.num, a.den * b.den);
public static BigFraction operator /(BigFraction a, BigFraction b) => new BigFraction(a.num * b.den, a.den * b.num);
public static bool operator ==(BigFraction a, BigFraction b) => a.num * b.den == a.den * b.num;
public static bool operator !=(BigFraction a, BigFraction b) => a.num * b.den != a.den * b.num;
public static bool operator >(BigFraction a, BigFraction b) => a.num * b.den > a.den * b.num;
public static bool operator <(BigFraction a, BigFraction b) => a.num * b.den < a.den * b.num;
public static bool operator >=(BigFraction a, BigFraction b) => a.num * b.den >= a.den * b.num;
public static bool operator <=(BigFraction a, BigFraction b) => a.num * b.den <= a.den * b.num;
public BigInteger GCD(BigInteger a, BigInteger b) => b == 0 ? a : GCD(b, a % b);
public BigFraction reciprocal{
get{return new BigFraction(den, num);}
public BigDecimal decimalForm{
get{return ((BigDecimal) num) / den;}
public BigFraction LimitDenominator(BigInteger size){
BigDecimal n = ((BigDecimal) num) / den;
BigInteger aN = (BigInteger) n;
BigInteger fractionTop = 0;
BigInteger fractionTopN1 = 1;
BigInteger fractionTopN2 = 1;
BigInteger fractionBot = 1;
BigInteger fractionBotN1 = 0;
BigInteger fractionBotN2 = 0;
BigInteger denominatorLimit = size;
BigInteger convergentLimit = BDMath.Pow(2, 30);
BigInteger intPart = (BigInteger) n;
for(int a = 0; a < 10000; a++){
fractionTopN2 = fractionTopN1;
fractionTopN1 = fractionTop;
fractionTop = aN * fractionTopN1 + fractionTopN2;
fractionBotN2 = fractionBotN1;
fractionBotN1 = fractionBot;
fractionBot = aN * fractionBotN1 + fractionBotN2;
if(fractionBot > denominatorLimit || aN > convergentLimit){
fractionTop = fractionTopN1;
fractionBot = fractionBotN1;
return new BigFraction(fractionTop + intPart * fractionBot, fractionBot);
public override string ToString() => den == 1 ? $"{num}" : $"{num} / {den}";
public BigComplex(BigDecimal R, BigDecimal I){
public static implicit operator BigComplex(int n) => new BigComplex(n, 0);
public static implicit operator BigComplex(double n) => new BigComplex(n, 0);
public static implicit operator BigComplex(BigDecimal n) => new BigComplex(n, 0);
public static explicit operator BigComplex(BigFraction n) => new BigComplex(n.decimalForm, 0);
public static BigComplex operator +(BigComplex z1, BigComplex z2) => new BigComplex(z1.Re + z2.Re, z1.Im + z2.Im);
public static BigComplex operator +(BigComplex z) => z;
public static BigComplex operator -(BigComplex z1, BigComplex z2) => new BigComplex(z1.Re - z2.Re, z1.Im - z2.Im);
public static BigComplex operator -(BigComplex z) => new BigComplex(-z.Re, -z.Im);
public static BigComplex operator *(BigComplex z1, BigComplex z2) => new BigComplex(z1.Re * z2.Re - z1.Im * z2.Im, z1.Im * z2.Re + z1.Re * z2.Im);
public static BigComplex operator /(BigComplex z1, BigComplex z2) =>
new BigComplex((z1.Re * z2.Re + z1.Im * z2.Im) / z2.SquaredNorm, (z1.Im * z2.Re - z1.Re * z2.Im) / z2.SquaredNorm);
public static bool operator ==(BigComplex z1, BigComplex z2) => z1.SquaredNorm == z2.SquaredNorm;
public static bool operator !=(BigComplex z1, BigComplex z2) => z1.SquaredNorm != z2.SquaredNorm;
public static bool operator <(BigComplex z1, BigComplex z2) => z1.SquaredNorm < z2.SquaredNorm;
public static bool operator >(BigComplex z1, BigComplex z2) => z1.SquaredNorm > z2.SquaredNorm;
public static bool operator <=(BigComplex z1, BigComplex z2) => z1.SquaredNorm <= z2.SquaredNorm;
public static bool operator >=(BigComplex z1, BigComplex z2) => z1.SquaredNorm >= z2.SquaredNorm;
public BigComplex Conjugate{
get{return new BigComplex(Re, -Im);}
get{return BDMath.Pow(Re * Re + Im * Im, 0.5);}
public BigDecimal SquaredNorm{
get{return Re * Re + Im * Im;}
public override string ToString(){
String ImString = Im >= 0 ? $"+ {Im}i" : $"- {-Im}i";
return Im == 0 ? "0" : (Im == -1 ? "- i" : (Im == 1 ? "i" : $"{Im}i"));
return $"{Re} {ImString}";
private static BigDecimal pi = 0;
public static BigDecimal PI{
term = (n % 2 == 0 ? 1 : -1) * Factorial(4 * n) * (1123 + 21460 * n);
term /= (Pow(Pow(4, n) * Factorial(n), 4) * Pow(882, 2 * n));
private static BigDecimal eulerNumber = 0;
public static BigDecimal E{
public static BigComplex I{
return new BigComplex(0, 1);
public static BigInteger Pow(BigInteger n1, BigInteger n2){
}else if(n2 == 0 || n1 == 1){
for(int a = 0; a < n2; a++){
public static BigDecimal Pow(BigDecimal n1, BigInteger n2){
}else if(n2 == 0 || n1 == 1){
for(int a = 0; a < n2; a++){
public static BigDecimal Pow(BigDecimal n1, BigDecimal n2) => Exp(Log(n1) * n2);
public static BigDecimal Pow(BigFraction n1, BigFraction n2) => Pow((BigDecimal) n1, (BigDecimal) n2);
public static BigInteger Factorial(BigInteger num){
for(int a = 1; a <= num; a++){
public static BigDecimal Abs(BigDecimal num) => num < 0 ? -num : num;
public static BigDecimal Abs(BigComplex num) => Pow(num.SquaredNorm, 0.5);
public static BigInteger Abs(BigInteger num) => num < 0 ? -num : num;
public static BigDecimal Exp(BigDecimal num){
bool isNegative = num <= 0;
return isNegative ? 1 / sum : sum;
public static BigComplex Exp(BigComplex num){
bool isNegative = num <= 0;
return isNegative ? 1 / sum : sum;
public static dynamic Log(BigDecimal num){
throw new ArithmeticException("Logarithms must be positive");
BigDecimal runningNum = 1;
BigDecimal runningNum = 1;
BigDecimal pastResult = 0;
while(Abs(pastResult - result) * BigDecimal.DecimalVal > 20){
result = result - 1 + num * Exp(-result);
public static BigDecimal Sin(BigDecimal num){
term = (n % 2 == 0 ? 1 : -1) * Pow(num, 2 * n + 1);
term /= Factorial(2 * n + 1);
public static BigDecimal Cos(BigDecimal num){
term = (n % 2 == 0 ? 1 : -1) * Pow(num, 2 * n);
term /= Factorial(2 * n);
public static BigDecimal Tan(BigDecimal num) => Sin(num) / Cos(num);