public static BigNumber operator +(BigNumber a, BigNumber b) { BigNumber r = new BigNumber(Math.Max(a.buffer.Length, b.buffer.Length)); //r.negative = (a.negative && !b.negative) || (!a.negative && b.negative); for (int i = 0; i < Math.Max(a.buffer.Length, b.buffer.Length); i++) { r.buffer[i] += (byte)(a.gb(i) + b.gb(i)); if (r.buffer[i] >= 100) { r.buffer[i + 1] += (byte)(r.buffer[i] / 100); //TODO: OVERFLOW r.buffer[i] = (byte)(r.buffer[i] % 100); } } return r; }
public static BigNumber Parse(string t, int size) { if (string.IsNullOrEmpty(t)) throw new ArgumentException("String to parse cannot be null or empty.", "t"); BigNumber v = new BigNumber(size); int i = 0; if (t[i++] == '-') v.negative = true; else i--; while (i < t.Length) { v.buffer[(t.Length - i - 1) / 2] += (byte)(byte.Parse(new string(new char[] { t[i] })) * ((t.Length - i - 1) % 2 == 1 ? 10 : 1)); i++; } return v; }
static void Sqrt(BigNumber src, BigNumber dst, int places) { int ii, nexp, tolerance, dplaces; bool bflag; if (src.signum <= 0) { if (src.signum == -1) { throw new BigNumberException("'Sqrt',Invalid Argument"); } } BigNumber last_x = new BigNumber(); BigNumber guess = new BigNumber(); BigNumber tmpN = new BigNumber(); BigNumber tmp7 = new BigNumber(); BigNumber tmp8 = new BigNumber(); BigNumber tmp9 = new BigNumber(); BigNumber.Copy(src, tmpN); nexp = src.exponent / 2; tmpN.exponent -= 2 * nexp; BigNumber.SQrtGuess(tmpN, guess); tolerance = places + 4; dplaces = places + 16; bflag = false; BigNumber.Neg(BigNumber.Ten, last_x); ii = 0; while (true) { BigNumber.Mul(tmpN, guess, tmp9); BigNumber.Mul(tmp9, guess, tmp8); BigNumber.Round(tmp8, tmp7, dplaces); BigNumber.Sub(BigNumber.Three, tmp7, tmp9); BigNumber.Mul(tmp9, guess, tmp8); BigNumber.Mul(tmp8, BigNumber.BN_OneHalf, tmp9); if (bflag) { break; } BigNumber.Round(tmp9, guess, dplaces); if (ii != 0) { BigNumber.Sub(guess, last_x, tmp7); if (tmp7.signum == 0) { break; } /* * if we are within a factor of 4 on the error term, * we will be accurate enough after the *next* iteration * is complete. (note that the sign of the exponent on * the error term will be a negative number). */ if ((-4 * tmp7.exponent) > tolerance) { bflag = true; } } BigNumber.Copy(guess, last_x); ii++; } BigNumber.Mul(tmp9, tmpN, tmp8); BigNumber.Round(tmp8, dst, places); dst.exponent += nexp; }
static private void IntPow(int places, BigNumber src, int mexp, BigNumber dst) { BigNumber A, B, C; int nexp, ii, signflag, local_precision; if (mexp == 0) { BigNumber.Copy(BigNumber.One, dst); return; } else { if (mexp > 0) { signflag = 0; nexp = mexp; } else { signflag = 1; nexp = -mexp; } } if (src.signum == 0) { BigNumber.SetZero(dst); return; } A = new BigNumber(); B = new BigNumber(); C = new BigNumber(); local_precision = places + 8; BigNumber.Copy(BigNumber.One, B); BigNumber.Copy(src, C); while (true) { ii = nexp & 1; nexp = nexp >> 1; if (ii != 0) /* exponent -was- odd */ { BigNumber.Mul(B, C, A); BigNumber.Round(A, B, local_precision); if (nexp == 0) { break; } } BigNumber.Mul(C, C, A); BigNumber.Round(A, C, local_precision); } if (signflag > 0) { BigNumber.Reziprocal(B, dst, places); } else { BigNumber.Round(B, dst, places); } }
static void Log(BigNumber src, BigNumber dst, int places) { BigNumber tmp0, tmp1, tmp2; int mexp, dplaces; if (src.signum <= 0) { throw new BigNumberException(" 'Log', Negative argument"); } tmp0 = new BigNumber(); tmp1 = new BigNumber(); tmp2 = new BigNumber(); dplaces = places + 8; mexp = src.exponent; if (mexp == 0 || mexp == 1) { BigNumber.Sub(src, BigNumber.One, tmp0); if (tmp0.signum == 0) /* is input exactly 1 ?? */ { /* if so, result is 0 */ BigNumber.SetZero(dst); return; } if (tmp0.exponent <= -4) { M_log_near_1(tmp0, dst, places); return; } } /* make sure our log(10) is accurate enough for this calculation */ /* (and log(2) which is called from M_log_basic_iteration) */ BigNumber.CheckLogPlaces(dplaces + 25); if (Math.Abs(mexp) <= 3) { M_log_basic_iteration(src, dst, places); } else { /* * use log (x * y) = log(x) + log(y) * * here we use y = exponent of our base 10 number. * * let 'C' = log(10) = 2.3025850929940.... * * then log(x * y) = log(x) + ( C * base_10_exponent ) */ BigNumber.Copy(src, tmp2); mexp = tmp2.exponent - 2; tmp2.exponent = 2; M_log_basic_iteration(tmp2, tmp0, dplaces); BigNumber.SetFromLong(tmp1, (long)mexp); BigNumber.Mul(tmp1, BN_lc_log10, tmp2); BigNumber.Add(tmp2, tmp0, tmp1); BigNumber.Round(tmp1, dst, places); } }
static private String ToIntString(BigNumber atm) { int ct, dl, numb, ii; ct = atm.exponent; dl = atm.dataLength; String result = String.Empty; byte numdiv = 0, numrem = 0; if (ct <= 0 || atm.signum == 0) { return("0"); } if (ct > 112) { BigNumber.Expand(atm, ct + 32); } ii = 0; if (atm.signum == -1) { ii = 1; result += "-"; } if (ct > dl) { numb = (dl + 1) >> 1; } else { numb = (ct + 1) >> 1; } int ucp = 0; while (true) { Unpack(atm.mantissa[ucp++], ref numdiv, ref numrem); result += (char)('0' + numdiv); result += (char)('0' + numrem); if (--numb == 0) { break; } } if (ct > dl) { for (int i = 0; i < (ct + 1 - dl); i++) { result += '0'; } } result = result.Substring(0, ct + ii); return(result); }
static private int SignificantDigits(BigNumber atm) { return(atm.dataLength); }
/// <summary> /// /// </summary> /// <param name="ctmp"></param> /// <param name="count"></param> static private void Scale(BigNumber ctmp, int count) { int ii, numb, ct; ct = count; byte numdiv = 0, numdiv2 = 0, numrem = 0; ii = (ctmp.dataLength + ct + 1) >> 1; if (ii > ctmp.mantissa.Length) { BigNumber.Expand(ctmp, (ii + 32)); } if ((ct & 1) != 0) /* move odd number first */ { ct--; ii = ((ctmp.dataLength + 1) >> 1) - 1; if ((ctmp.dataLength & 1) == 0) { /* * original datalength is even: * * uv wx yz becomes --> 0u vw xy z0 */ numdiv = 0; while (true) { Unpack(ctmp.mantissa[ii], ref numdiv2, ref numrem); ctmp.mantissa[ii + 1] = (byte)(10 * numrem + numdiv); numdiv = numdiv2; if (ii == 0) { break; } ii--; } ctmp.mantissa[0] = numdiv2; } else { /* * original datalength is odd: * * uv wx y0 becomes --> 0u vw xy */ Unpack(ctmp.mantissa[ii], ref numdiv2, ref numrem); if (ii == 0) { ctmp.mantissa[0] = numdiv2; } else { while (true) { Unpack(ctmp.mantissa[ii - 1], ref numdiv, ref numrem); ctmp.mantissa[ii] = (byte)(10 * numrem + numdiv2); numdiv2 = numdiv; if (--ii == 0) { break; } } ctmp.mantissa[0] = numdiv; } } ctmp.exponent++; ctmp.dataLength++; } /* ct is even here */ if (ct > 0) { numb = (ctmp.dataLength + 1) >> 1; ii = ct >> 1; byte[] newData = new byte[ctmp.mantissa.Length]; Array.Copy(ctmp.mantissa, 0, newData, ii, numb); for (int i = 0; i < ii; i++) { newData[i] = 0; } ctmp.mantissa = newData; ctmp.dataLength += ct; ctmp.exponent += ct; } }
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); }
/// <summary> /// compare 2 numbers /// </summary> /// <param name="ltmp"></param> /// <param name="rtmp"></param> /// <returns></returns> static public int Compare(BigNumber ltmp, BigNumber rtmp) { int llen, rlen, lsign, rsign, i, j, lexp, rexp; llen = ltmp.dataLength; rlen = rtmp.dataLength; lsign = ltmp.signum; rsign = rtmp.signum; lexp = ltmp.exponent; rexp = rtmp.exponent; if (rsign == 0) { return(lsign); } if (lsign == 0) { return(-rsign); } if (lsign == -rsign) { return(lsign); } if (lexp > rexp) { goto E1; } if (lexp < rexp) { goto E2; } if (llen < rlen) { j = (llen + 1) >> 1; } else { j = (rlen + 1) >> 1; } for (i = 0; i < j; i++) { if (ltmp.mantissa[i] > rtmp.mantissa[i]) { goto E1; } if (ltmp.mantissa[i] < rtmp.mantissa[i]) { goto E2; } } if (llen == rlen) { return(0); } else { if (llen > rlen) { goto E1; } else { goto E2; } } E1: if (lsign == 1) { return(1); } else { return(-1); } E2: if (lsign == 1) { return(-1); } else { return(1); } }
public BigNumber(BigNumber anotherBigNumber) { length = anotherBigNumber.length; sign = anotherBigNumber.sign; data = anotherBigNumber.data; }
public static bool IsZero(BigNumber number) { return(number.length == 0 || (number.length == 1 && number.data[0] == 0)); }
static public void Reziprocal(BigNumber src, BigNumber dst, int places) { BigNumber.Div(BigNumber.One, src, dst, places); }
static private String ToExpString(BigNumber atm, int digits) { int i, index, first, max_i, num_digits, dec_places; byte numdiv = 0, numrem = 0; BigNumber ctmp = new BigNumber(); String res = ""; dec_places = digits; if (dec_places < 0) { BigNumber.Copy(atm, ctmp); } else { BigNumber.Round(atm, ctmp, dec_places); } if (ctmp.signum == 0) { if (dec_places < 0) { res = "0.0E+0"; } else { res = "0"; if (dec_places > 0) { res += "."; } for (i = 0; i < dec_places; i++) { res += "0"; } res += "E+0"; } return(res); } max_i = (ctmp.dataLength + 1) >> 1; if (dec_places < 0) { num_digits = ctmp.dataLength; } else { num_digits = dec_places + 1; } if (ctmp.signum == -1) { res += '-'; } first = 1; i = 0; index = 0; while (true) { if (index >= max_i) { numdiv = 0; numrem = 0; } else { Unpack(ctmp.mantissa[index], ref numdiv, ref numrem); } index++; res += (char)('0' + numdiv); if (++i == num_digits) { break; } if (first != 0) { first = 0; res += '.'; } res += (char)('0' + numrem); if (++i == num_digits) { break; } } i = ctmp.exponent - 1; if (i >= 0) { res += "E+" + i; } else if (i < 0) { res += "E" + i; } return(res); }
static public void Div(BigNumber aa, BigNumber bb, BigNumber rr) { int places = BigNumber.MaxDigits(aa, bb); BigNumber.Div(aa, bb, rr, places); }
public static void DoTest() { BigNumber A = 0, B = 0, C = 0; BigNumber PI = new BigNumber(); // assignment by string A = "12345"; Console.WriteLine("assigned value was: " + A.ToFullString() + "(" + A.ToString() + ")"); // assignment from hexadecimal string A = "0xff"; Console.WriteLine("assigned value was: " + A.ToFullString() + "(" + A.ToString() + ")"); A = "0x1ff"; Console.WriteLine("assigned value was: " + A.ToFullString() + "(" + A.ToString() + ")"); A = "0x123456789"; Console.WriteLine("assigned value was: " + A.ToFullString() + "(" + A.ToString() + ")"); A = "0xFeDcBafedcba"; Console.WriteLine("assigned value was: " + A.ToFullString() + "(" + A.ToString() + ")"); // assignment from binary string A = "%10001000"; Console.WriteLine("assigned value was: " + A.ToFullString() + "(" + A.ToString() + ")"); A = "%11011011100111000111000111100011010101010101"; Console.WriteLine("assigned value was: " + A.ToFullString() + "(" + A.ToString() + ")"); // assignment by double A = 123.45; B = 0.12345; Console.WriteLine("assigned value was: " + A.ToFullString() + "(" + A.ToString() + ")"); // assignment by string in exponential form x = a*10^y. 10E3 = 10*10^^3 = 10000 A = "10E3"; // 10E3 = 10*10^3 = 10000 B = "1E4"; // 1E4 = 1*10^4 = 10000 C = 10000; Console.WriteLine("assigned value was: " + A.ToFullString() + "(" + A.ToString() + ")"); Console.WriteLine("10000 = " + A.ToFullString() + " = " + B.ToFullString() + " = " + C.ToFullString()); A = 1; B = 2; C = 0; C = A + B; Console.WriteLine("the result of " + A.ToFullString() + "+" + B.ToFullString() + "=" + C.ToFullString()); // addition of BigNumber + double C = A + 3.2; // addition of double + BigNumber C = 3.1 + B; A = "5.141592"; B = "2.91827"; C = A - B; Console.WriteLine("the result of " + A.ToFullString() + "-" + B.ToFullString() + "=" + C.ToFullString()); C = A * B; Console.WriteLine("the result of " + A.ToFullString() + "*" + B.ToFullString() + "=" + C.ToFullString()); A = 5.0; B = 3.0; C = A * B; Console.WriteLine("the result of " + A.ToFullString() + "*" + B.ToFullString() + "=" + C.ToFullString()); A = 4; B = 0.5; C = A.Pow(B); Console.WriteLine("the result of " + A.ToFullString() + " pow " + B.ToFullString() + "=" + C.ToFullString()); A = 0.5; B = "5E-1"; C = A.Pow(B, 16); Console.WriteLine("the result of " + A.ToFullString() + " pow " + B.ToFullString() + "=" + C.ToFullString()); A = "1e3"; // "10E2"; // "1E3 = 1000"; C = A.Log10(); Console.WriteLine("the result of " + A.ToFullString() + " Log10 =" + C.ToFullString()); A = "10E3"; B = "1E4"; C = 10000; A = BigNumber.BN_E; C = A.Log(); Console.WriteLine("the result of " + A.ToString() + " Log =" + C.ToFullString()); A = 3.0; C = A.Rez(); Console.WriteLine("the result of " + A.ToString() + " Rez =" + C.ToFullString()); int NumPlaces = 4; A = 1.53456; C = A.Round(NumPlaces); Console.WriteLine("the result of " + A.ToString() + " Round(" + NumPlaces + ") =" + C.ToFullString()); NumPlaces = 2; C = A.Round(NumPlaces); Console.WriteLine("the result of " + A.ToString() + " Round(" + NumPlaces + ") =" + C.ToFullString()); NumPlaces = 0; C = A.Round(NumPlaces); Console.WriteLine("the result of " + A.ToString() + " Round(" + NumPlaces + ") =" + C.ToFullString()); NumPlaces = 16; A = 2.0; C = A.Sqrt(NumPlaces); Console.WriteLine("the result of " + A.ToString() + " Sqrt(" + NumPlaces + ") =" + C.ToFullString()); A = 1.0; B = 0; try { C = A / B; } catch (BigNumberException ex) { Console.WriteLine("Exception in operation: " + ex.Message); } A = 1.0; for (int i = 1; i <= 1000; i++) { A = A * i; } Console.WriteLine("the result of 1000!=" + A.ToFullString()); A = A.Round(numDefaultPlaces); Console.WriteLine("the result of 1000!=" + A.ToString()); DateTime before = DateTime.Now; NumPlaces = 5000; CalculatePiAGM(PI, NumPlaces); TimeSpan ts = DateTime.Now - before; Console.WriteLine("time for " + NumPlaces + " digits of PI: " + ts.TotalMilliseconds + "[ms]"); Console.WriteLine(PI.ToFullString()); Console.WriteLine("Press 'x' key to quit test"); //while (true) //{ // ConsoleKeyInfo i = Console.ReadKey(); // if (i.KeyChar == 'x') break; //} }
static private void Mul(BigNumber aa, BigNumber bb, BigNumber rr) { int ai, itmp, nexp, ii, jj, indexa, indexb, index0, numdigits; sbyte sign; sign = (sbyte)(aa.signum * bb.signum); nexp = aa.exponent + bb.exponent; if (sign == 0) { BigNumber.SetZero(rr); return; } numdigits = aa.dataLength + bb.dataLength; indexa = (aa.dataLength + 1) >> 1; indexb = (bb.dataLength + 1) >> 1; if (indexa >= 48 && indexb >= 48) { BigNumber.FastMul(aa, bb, rr); return; } ii = (numdigits + 1) >> 1; if (ii >= rr.mantissa.Length) { BigNumber.Expand(rr, ii + 32); } index0 = indexa + indexb; for (int i = 0; i < index0; i++) { rr.mantissa[i] = 0; } ii = indexa; while (true) { index0--; int crp = index0; jj = indexb; ai = (int)aa.mantissa[--ii]; while (true) { itmp = ai * bb.mantissa[--jj]; rr.mantissa[crp - 1] += s_MsbLookupMult[itmp]; rr.mantissa[crp] += s_LsbLookupMult[itmp]; if (rr.mantissa[crp] >= 100) { rr.mantissa[crp] -= 100; rr.mantissa[crp - 1] += 1; } crp--; if (rr.mantissa[crp] >= 100) { rr.mantissa[crp] -= 100; rr.mantissa[crp - 1] += 1; } if (jj == 0) { break; } } if (ii == 0) { break; } } rr.signum = sign; rr.exponent = nexp; rr.dataLength = numdigits; 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); }
static private void SetFromString(BigNumber atm, String value, bool isStrainghtDigitsOnly = false) { SetZero(atm); int p = 0; sbyte sign = 1; int exponent = 0; if (isStrainghtDigitsOnly == false) { value = value.Trim(); // trim whitespace value = value.ToLower(); // convert to lower //value = UtilityHandler.ToLowerFast(value); int cp = value.IndexOf("0x"); // hexadezimalnumber if (cp >= 0) { value = value.Substring(cp + 2, value.Length - (cp + 2)); BigNumber.SetFromHexString(atm, value); return; } cp = value.IndexOf("%"); // binary format number if (cp >= 0) { value = value.Substring(cp + 1, value.Length - (cp + 1)); BigNumber.SetFromBinaryString(atm, value); return; } cp = value.IndexOf("e"); if (cp > 0) // e cannot be leading { String ex = value.Substring(cp + 1, value.Length - (cp + 1)); exponent = Convert.ToInt32(ex); value = value.Substring(0, cp); } } if (value.Contains("+")) { value = value.Replace("+", ""); // remove optional '+' character } else if (value.Contains("-")) { sign = -1; value = value.Replace("-", ""); } value = value.Replace(",", "."); int j = value.IndexOf("."); if (j == -1) { value = value + '.'; j = value.IndexOf("."); } if (j > 0) { exponent += j; value = value.Replace(".", ""); } int i = value.Length; atm.dataLength = i; if ((i % 2) != 0) { value = value + '0'; } j = value.Length >> 1; if (value.Length > atm.mantissa.Length) { BigNumber.Expand(atm, atm.dataLength + 28); } byte ch = 0; int zflag = 1; for (i = 0, p = 0; i < j; i++) { ch = (byte)(value[p++] - '0'); if ((ch = (byte)((byte)(10 * ch) + (byte)(value[p++] - '0'))) != 0) { zflag = 0; } if (((int)ch & 0xFF) >= 100) { // Error! SetZero(atm); return; } atm.mantissa[i] = ch; atm.mantissa[i + 1] = 0; } atm.exponent = exponent; atm.signum = sign; if (zflag != 0) { atm.exponent = 0; atm.signum = 0; atm.dataLength = 1; atm.mantissa[0] = 0; } else { Normalize(atm); } }
// // 1 2 3 k // pi = 2 + --- * (2 + --- * (2 + --- * (2 + ... (2 + ---- * (2 + ... ))...))) // 3 5 7 2k+1 // Calculation of pi to 32372 decimal digits */ // Size of program: 152 characters */ // After Dik T. Winter, CWI Amsterdam */ // // unsigned a=1e4,b,c=113316,d,e,f[113316],g,h,i; // main(){for(;b=c,c-=14;i=printf("%04d",e+d/a),e=d%a) // while(g=--b*2)d=h*b+a*(i?f[b]:a/5),h=d/--g,f[b]=d-g*h;} // // unsigned a=1e4,b,c=113316,d,e,f[113316],g,h,i; // // main() // { // for(;b=c,c-=14;i=printf("%04d",e+d/a),e=d%a) // { // while(g=--b*2) // { // d = h*b+a*(i?f[b]:a/5); // h = d/--g; // f[b]= d-g*h; // } // } // } static private void CalculatePiSpigot(BigNumber outv, int places) { }
/// <summary> /// normalize number /// </summary> /// <param name="atm"></param> static private void Normalize(BigNumber atm) { if (atm.signum == 0) { return; } int ucp = 0; int i; int index; int datalength = atm.dataLength; int exponent = atm.exponent; byte numdiv = 0, numrem = 0, numrem2 = 0; BigNumber.Pad(atm, datalength + 3); // remove leading zeroes while (true) { // extract first 2 nibbles Unpack(atm.mantissa[0], ref numdiv, ref numrem); // if first digit is greater 1 we are done if (numdiv >= 1) { break; } // otherwise we have leading zeroes index = (datalength + 1) >> 1; if (numrem == 0) // both nibbles are 0 { i = 0; ucp = 0; while (true) { if (atm.mantissa[ucp] != 0) { break; } ucp++; i++; } byte[] copy = new byte[atm.mantissa.Length]; Array.Copy(atm.mantissa, ucp, copy, 0, (index + 1 - i)); atm.mantissa = copy; datalength -= 2 * i; exponent -= 2 * i; } else { for (i = 0; i < index; i++) { Unpack(atm.mantissa[i + 1], ref numdiv, ref numrem2); atm.mantissa[i] = (byte)(10 * numrem + numdiv); numrem = numrem2; } datalength--; exponent--; } } // remove trailing zeroes while (true) { index = ((datalength + 1) >> 1) - 1; if ((datalength & 1) == 0) /* back-up full bytes at a time if the */ { /* current length is an even number */ ucp = index; if (atm.mantissa[ucp] == 0) { while (true) { datalength -= 2; index--; ucp--; if (atm.mantissa[ucp] != 0) { break; } } } } Unpack(atm.mantissa[index], ref numdiv, ref numrem); if (numrem != 0) /* last digit non-zero, all done */ { break; } if ((datalength & 1) != 0) /* if odd, then first char must be non-zero */ { if (numdiv != 0) { break; } } if (datalength == 1) { atm.signum = 0; exponent = 0; break; } datalength--; } atm.dataLength = datalength; atm.exponent = exponent; }
/****************************************************************************/ /* * define a notation for a function 'R' : * * * * 1 * R (a0, b0) = ------------------------------ * * ---- * \ * \ n-1 2 2 * 1 - | 2 * (a - b ) * / n n * / * ---- * n >= 0 * * * where a, b are the classic AGM iteration : * * * a = 0.5 * (a + b ) * n+1 n n * * * b = sqrt(a * b ) * n+1 n n * * * * define a variable 'c' for more efficient computation : * * 2 2 2 * c = 0.5 * (a - b ) , c = a - b * n+1 n n n n n * */ /****************************************************************************/ static void LogAGMRFunc(BigNumber aa, BigNumber bb, BigNumber rr, int places) { BigNumber tmp1, tmp2, tmp3, tmp4, tmpC2, sum, pow_2, tmpA0, tmpB0; int tolerance, dplaces; tmpA0 = new BigNumber(); tmpB0 = new BigNumber(); tmpC2 = new BigNumber(); tmp1 = new BigNumber(); tmp2 = new BigNumber(); tmp3 = new BigNumber(); tmp4 = new BigNumber(); sum = new BigNumber(); pow_2 = new BigNumber(); tolerance = places + 8; dplaces = places + 16; BigNumber.Copy(aa, tmpA0); BigNumber.Copy(bb, tmpB0); BigNumber.Copy(BigNumber.BN_OneHalf, pow_2); BigNumber.Mul(aa, aa, tmp1); /* 0.5 * [ a ^ 2 - b ^ 2 ] */ BigNumber.Mul(bb, bb, tmp2); BigNumber.Sub(tmp1, tmp2, tmp3); BigNumber.Mul(BigNumber.BN_OneHalf, tmp3, sum); while (true) { BigNumber.Sub(tmpA0, tmpB0, tmp1); /* C n+1 = 0.5 * [ An - Bn ] */ BigNumber.Mul(BigNumber.BN_OneHalf, tmp1, tmp4); /* C n+1 */ BigNumber.Mul(tmp4, tmp4, tmpC2); /* C n+1 ^ 2 */ /* do the AGM */ BigNumber.Add(tmpA0, tmpB0, tmp1); BigNumber.Mul(BigNumber.BN_OneHalf, tmp1, tmp3); BigNumber.Mul(tmpA0, tmpB0, tmp2); BigNumber.Sqrt(tmp2, tmpB0, dplaces); BigNumber.Round(tmp3, tmpA0, dplaces); /* end AGM */ BigNumber.Mul(BigNumber.Two, pow_2, tmp2); BigNumber.Copy(tmp2, pow_2); BigNumber.Mul(tmpC2, pow_2, tmp1); BigNumber.Add(sum, tmp1, tmp3); if ((tmp1.signum == 0) || ((-2 * tmp1.exponent) > tolerance)) { break; } BigNumber.Round(tmp3, sum, dplaces); } BigNumber.Sub(BigNumber.One, tmp3, tmp4); BigNumber.Reziprocal(tmp4, rr, places); }
static private int Digits(BigNumber atm) { return(atm.dataLength < sMinPrecision ? sMinPrecision : atm.dataLength); }
static private String ToFullString(BigNumber atm) { if (atm == 0) { return("0"); } StringBuilder sb = new StringBuilder(); sb.Append(""); String res = ""; byte numdiv = 0, numrem = 0; int max_i = (atm.dataLength + 1) >> 1; int exp = atm.exponent; for (int i = 0; i < max_i; i++) { BigNumber.Unpack(atm.mantissa[i], ref numdiv, ref numrem); //res += (char)('0' + numdiv); //res += (char)('0' + numrem); sb.Append((char)('0' + numdiv)); sb.Append((char)('0' + numrem)); } res = sb.ToString().Substring(0, atm.dataLength); sb.Clear(); sb.Append(res); if (exp > 0) { for (int i = res.Length; i < exp; i++) { //res += "0"; sb.Append("0"); } if (exp < res.Length) { //res = res.Insert(exp , "."); sb.Insert(exp, "."); } } else if (exp <= 0) { while (exp++ <= 0) { //res = "0" + res; sb.Insert(0, "0"); } res = sb.ToString(); if (exp <= res.Length) { //res = res.Insert(1, "."); sb.Insert(1, "."); } } if (atm.signum < 0) /*res = res.Insert(0, "-");*/ { sb.Insert(0, "-"); } res = sb.ToString(); return(res); }