public static eeNumber operator *(eeNumber num1_orig, eeNumber num2_orig) { eeNumber num1 = num1_orig.Copy(), num2 = num2_orig.Copy(); // if either num is 0, return 0 if (num1 == ZERO || num2 == ZERO) { return(new eeNumber(0)); } bool negate = false; /* first account for negatives */ // if either num is negative if (num1.negative ^ num2.negative) { // set both to non-negative to multiply them num1.negative = false; num2.negative = false; // apply negative afterwards negate = true; } else if (num1.negative && num2.negative) { // otherwise, negatives just cancel out num1.negative = false; num2.negative = false; } eeNumber final; // if only one num is a fraction if (num1.IsFrac() ^ num2.IsFrac()) { eeNumber frac = num1.denominator != null ? num1 : num2, reg = num1.denominator != null ? num2 : num1; var den = frac.PopDenominator(); var newNum = (frac * reg) / den; final = newNum; } // if both nums are fractions else if (num1.IsFrac() && num2.IsFrac()) { eeNumber frac1 = num1.PopDenominator(), frac2 = num2.PopDenominator(); final = (num1 * num2) / (frac1 * frac2); } // regular nums else { // Reverse because we're going from right to left. byte[] lhs = num1.bytes.Reverse().ToArray(), rhs = num2.bytes.Reverse().ToArray(); // new digit eeNumber finalNum = new eeNumber(0); // foreach digit in on the top num for (int i = 0; i < rhs.Length; i++) { byte carry = 0; List <byte> product = new List <byte>(); // foreach digit in the bottom num for (int j = 0; j < lhs.Length; j++) { // multiply them byte digitProduct = (byte)(lhs[j] * rhs[i]); if (carry != 0) { digitProduct += carry; carry = 0; } if (digitProduct > 9) { carry = (byte)(digitProduct / 10); digitProduct %= 10; } product.Add(digitProduct); } // If carry is left if (carry != 0) { product.Add(carry); } product.Reverse(); // Add the needed amount of trailing zeros for place value for (int z = 0; z < i; z++) { product.Add(0); } finalNum += new eeNumber(product.ToArray()); } final = finalNum; } final.negative = negate; return(final); }
public static eeNumber operator /(eeNumber num1_orig, eeNumber num2_orig) { /* eeNumbers do not perform traditional division. That is only done * when the number needs to be approximated for a text representation. * For divison, we always keep the fractional form for arbitrary accuracy. */ eeNumber num1 = num1_orig.Copy(), num2 = num2_orig.Copy(); if (num2 == ZERO) { throw new DivisionByZeroError(num1); } bool negate = false; /* first, account for negatives */ // if either num is negative if (num1.negative ^ num2.negative) { // set both to non-negative to multiply them num1.negative = false; num2.negative = false; // apply negative afterwards negate = true; } else if (num1.negative && num2.negative) { // otherwise, negatives just cancel out num1.negative = false; num2.negative = false; } /* then, divide */ bool a = num1.IsFrac(), b = num2.IsFrac(); // frac divided by num if (a && !b) { num1.denominator *= num2; num1.negative = negate; num1.Simplify(); return(num1); } // num divided by num else if (!a && !b) { // check if right is a factor of left if (num1 > num2) { var m = num1 % num2; if (m == ZERO) { return(num1 % num2); } } num1.denominator = num2; num1.negative = negate; num1.Simplify(); return(num1); } // num divided by frac else if (!a && b) { eeNumber numerator = num1 * num2.denominator; eeNumber denominator = num2; var newNum = numerator / denominator; newNum.negative = negate; return(newNum); } // frac divided by frac else { var denom1 = num1.PopDenominator(); eeNumber numerator = num1 * num2.PopDenominator(); eeNumber denominator = num2 * denom1; var newNum = numerator / denominator; newNum.negative = negate; return(newNum); } }
// Warning: Subtraction will destroy the contents of num2 and set the contents of num1 to the result // Make sure to pass a copy of num2 if you are keeping its value public static eeNumber operator -(eeNumber num1_orig, eeNumber num2_orig) { eeNumber num1 = num1_orig.Copy(), num2 = num2_orig.Copy(); // If either number is a fraction, cross multiply if (num1.IsFrac() || num2.IsFrac()) { eeNumber frac1 = num1.PopDenominator(), frac2 = num2.PopDenominator(); num1 *= frac2; num2 *= frac1; var ret = (num1 - num2) / (frac1 * frac2); ret.TrimZeros(); ret.Simplify(); return(ret); } // if the two nums are the same if (num1 == num2) { return(ZERO.Copy()); } // if first num is negative else if (num1.negative && !num2.negative) { // add them then negate it num1.negative = false; var sum = num1 + num2; sum.negative = true; return(sum); } // if second num is negative else if (num2.negative && !num1.negative) { // minus and negatives cancel num2.negative = false; return(num1 + num2); } // If they're both negative else if (num1.negative && num2.negative) { // Treat this as adding a negative to a positive num2.negative = false; return(num1 + num2); } // If we're going to get a negative answer bool negate = false; if (num2 > num1) { // reverse the two var buf = num1; num1 = num2; num2 = buf; // and negate negate = true; } // Reverse because we're subtracting from right to left. byte[] l_bytes = num1.bytes.Reverse().ToArray(), r_bytes = num2.bytes.Reverse().ToArray(); bool carry = false; int i; for (i = 0; i < r_bytes.Length; i++) { // Account for the previous carry if (carry) { r_bytes[i]++; carry = false; } // Subtract the digits byte digitDiff; if (l_bytes[i] < r_bytes[i]) // account for carry { digitDiff = (byte)((10 + l_bytes[i]) - r_bytes[i]); carry = true; } else { digitDiff = (byte)(l_bytes[i] - r_bytes[i]); } // Set the digit l_bytes[i] = digitDiff; } // If there is still carry left while (carry) { // subtract one from the next value if (l_bytes[i] == 0) { l_bytes[i] = 9; i++; } else { l_bytes[i] -= 1; carry = false; } } // Put it in order again l_bytes = l_bytes.Reverse().ToArray(); num1.bytes = l_bytes; num1.negative = negate; num1.TrimZeros(); return(num1); }