public BigNumber Abs() { BigNumber res = 0; BigNumber.Abs(res, this); return(res); }
static public void Sub(BigNumber src, BigNumber dst, BigNumber result) { int itmp, j, ChangeOrderFlag, icompare, aexp, bexp, borrow, adigits, bdigits; sbyte sign; BigNumber A = 0, B = 0; if (dst.signum == 0) { BigNumber.Copy(src, result); return; } if (src.signum == 0) { BigNumber.Copy(dst.Neg(), result); return; } if (src.signum == 1 && dst.signum == -1) { dst.signum = 1; Add(src, dst, result); dst.signum = -1; return; } if (src.signum == -1 && dst.signum == 1) { dst.signum = -1; Add(src, dst, result); dst.signum = 1; return; } BigNumber.Abs(A, src); BigNumber.Abs(B, dst); if ((icompare = Compare(A, B)) == 0) { SetZero(result); return; } if (icompare == 1) /* |a| > |b| (do A-B) */ { ChangeOrderFlag = 1; sign = src.signum; } else /* |b| > |a| (do B-A) */ { ChangeOrderFlag = 0; sign = (sbyte)-(src.signum); } aexp = A.exponent; bexp = B.exponent; if (aexp > bexp) { Scale(B, (aexp - bexp)); } if (aexp < bexp) { Scale(A, (bexp - aexp)); } adigits = A.dataLength; bdigits = B.dataLength; if (adigits > bdigits) { Pad(B, adigits); } if (adigits < bdigits) { Pad(A, bdigits); } if (ChangeOrderFlag == 1) // |a| > |b| (do A-B) { Copy(A, result); j = (result.dataLength + 1) >> 1; borrow = 0; while (true) { j--; itmp = ((int)result.mantissa[j] - ((int)B.mantissa[j] + borrow)); if (itmp >= 0) { result.mantissa[j] = (byte)itmp; borrow = 0; } else { result.mantissa[j] = (byte)(100 + itmp); borrow = 1; } if (j == 0) { break; } } } else // |b| > |a| (do B-A) instead { Copy(B, result); j = (result.dataLength + 1) >> 1; borrow = 0; while (true) { j--; itmp = (int)result.mantissa[j] - ((int)A.mantissa[j] + borrow); if (itmp >= 0) { result.mantissa[j] = (byte)itmp; borrow = 0; } else { result.mantissa[j] = (byte)(100 + itmp); borrow = 1; } if (j == 0) { break; } } } result.signum = sign; BigNumber.Normalize(result); }
static private void Div(BigNumber aa, BigNumber bb, BigNumber rr, int places) { int j, k, m, b0, nexp, indexr, icompare, iterations; sbyte sign; long trial_numer; BigNumber M_div_worka = new BigNumber(); BigNumber M_div_workb = new BigNumber(); BigNumber M_div_tmp7 = new BigNumber(); BigNumber M_div_tmp8 = new BigNumber(); BigNumber M_div_tmp9 = new BigNumber(); sign = (sbyte)(aa.signum * bb.signum); if (sign == 0) /* one number is zero, result is zero */ { if (bb.signum == 0) { throw new BigNumberException("Division by Zero"); } BigNumber.SetZero(rr); return; } if (bb.mantissa[0] >= 50) { BigNumber.Abs(M_div_worka, aa); BigNumber.Abs(M_div_workb, bb); } else /* 'normal' step D1 */ { k = 100 / (bb.mantissa[0] + 1); BigNumber.SetFromLong(M_div_tmp9, (long)k); BigNumber.Mul(M_div_tmp9, aa, M_div_worka); BigNumber.Mul(M_div_tmp9, bb, M_div_workb); M_div_worka.signum = 1; M_div_workb.signum = 1; } b0 = 100 * (int)M_div_workb.mantissa[0]; if (M_div_workb.dataLength >= 3) { b0 += M_div_workb.mantissa[1]; } nexp = M_div_worka.exponent - M_div_workb.exponent; if (nexp > 0) { iterations = nexp + places + 1; } else { iterations = places + 1; } k = (iterations + 1) >> 1; /* required size of result, in bytes */ if (k > rr.mantissa.Length) { BigNumber.Expand(rr, k + 32); } /* clear the exponent in the working copies */ M_div_worka.exponent = 0; M_div_workb.exponent = 0; /* if numbers are equal, ratio == 1.00000... */ if ((icompare = BigNumber.Compare(M_div_worka, M_div_workb)) == 0) { iterations = 1; rr.mantissa[0] = 10; nexp++; } else /* ratio not 1, do the real division */ { if (icompare == 1) /* numerator > denominator */ { nexp++; /* to adjust the final exponent */ M_div_worka.exponent += 1; /* multiply numerator by 10 */ } else /* numerator < denominator */ { M_div_worka.exponent += 2; /* multiply numerator by 100 */ } indexr = 0; m = 0; while (true) { /* * Knuth step D3. Only use the 3rd -> 6th digits if the number * actually has that many digits. */ trial_numer = 10000L * (long)M_div_worka.mantissa[0]; if (M_div_worka.dataLength >= 5) { trial_numer += 100 * M_div_worka.mantissa[1] + M_div_worka.mantissa[2]; } else { if (M_div_worka.dataLength >= 3) { trial_numer += 100 * M_div_worka.mantissa[1]; } } j = (int)(trial_numer / b0); /* * Since the library 'normalizes' all the results, we need * to look at the exponent of the number to decide if we * have a lead in 0n or 00. */ if ((k = 2 - M_div_worka.exponent) > 0) { while (true) { j /= 10; if (--k == 0) { break; } } } if (j == 100) /* qhat == base ?? */ { j = 99; /* if so, decrease by 1 */ } BigNumber.SetFromLong(M_div_tmp8, (long)j); BigNumber.Mul(M_div_tmp8, M_div_workb, M_div_tmp7); /* * Compare our q-hat (j) against the desired number. * j is either correct, 1 too large, or 2 too large * per Theorem B on pg 272 of Art of Compter Programming, * Volume 2, 3rd Edition. * * The above statement is only true if using the 2 leading * digits of the numerator and the leading digit of the * denominator. Since we are using the (3) leading digits * of the numerator and the (2) leading digits of the * denominator, we eliminate the case where our q-hat is * 2 too large, (and q-hat being 1 too large is quite remote). */ if (BigNumber.Compare(M_div_tmp7, M_div_worka) == 1) { j--; BigNumber.Sub(M_div_tmp7, M_div_workb, M_div_tmp8); BigNumber.Copy(M_div_tmp8, M_div_tmp7); } /* * Since we know q-hat is correct, step D6 is unnecessary. * * Store q-hat, step D5. Since D6 is unnecessary, we can * do D5 before D4 and decide if we are done. */ rr.mantissa[indexr++] = (byte)j; /* j == 'qhat' */ m += 2; if (m >= iterations) { break; } /* step D4 */ BigNumber.Sub(M_div_worka, M_div_tmp7, M_div_tmp9); /* * if the subtraction yields zero, the division is exact * and we are done early. */ if (M_div_tmp9.signum == 0) { iterations = m; break; } /* multiply by 100 and re-save */ M_div_tmp9.exponent += 2; BigNumber.Copy(M_div_tmp9, M_div_worka); } } rr.signum = sign; rr.exponent = nexp; rr.dataLength = iterations; BigNumber.Normalize(rr); }
static private void CalculatePiMachin(BigNumber outv, int places) { BigNumber curanswer; BigNumber lastanswer; BigNumber term5; BigNumber term239; BigNumber term5m; BigNumber term239m; BigNumber diff; BigNumber lim; int n5; int n239; bool b5termdone = false; bool b239termdone = false; lim = 1; lim /= (Math.Pow(10, places)); n5 = 0; n239 = 0; term5 = 16; term5 /= 5; term239 = 4; term239 /= 239; curanswer = 0; lastanswer = 0; while (b5termdone == false && b239termdone == false) { lastanswer = curanswer; term5m = term5; term5m /= n5 * 2 + 1; term239m = term239; term239m /= n239 * 2 + 1; if (n5 % 2 == 0) { curanswer += term5m; /* n5 is even */ } else { curanswer -= term5m; /* n5 is odd */ } if (n239 % 2 == 0) { curanswer -= term239m; /* n239 is even */ } else { curanswer += term239m; /* n239 is odd */ } term5 /= 25; // 5*5 n5++; term239 /= 57121; // 239 * 239; n239++; diff = lastanswer - curanswer; BigNumber.Abs(diff, diff); if (diff < lim) { break; } } BigNumber.Round(curanswer, outv, places); }