public BigNumber Round(int places) { BigNumber res = 0; BigNumber.Round(this, res, places); return(res); }
static void M_log_basic_iteration(BigNumber nn, BigNumber rr, int places) { BigNumber tmp0, tmp1, tmp2, tmpX; if (places < 360) { BigNumber.M_log_solve_cubic(nn, rr, places); } else { tmp0 = new BigNumber(); tmp1 = new BigNumber(); tmp2 = new BigNumber(); tmpX = new BigNumber(); BigNumber.M_log_solve_cubic(nn, tmpX, 110); BigNumber.Neg(tmpX, tmp0); BigNumber.Exp(tmp0, tmp1, (places + 8)); BigNumber.Mul(tmp1, nn, tmp2); BigNumber.Sub(tmp2, BigNumber.One, tmp1); BigNumber.M_log_near_1(tmp1, tmp0, (places - 104)); BigNumber.Add(tmpX, tmp0, tmp1); BigNumber.Round(tmp1, rr, places); } }
static void Log10(BigNumber src, BigNumber dst, int places) { BigNumber tmp8 = new BigNumber(); BigNumber tmp9 = new BigNumber(); int dplaces = places + 4; BigNumber.CheckLogPlaces(dplaces + 45); BigNumber.Log(src, tmp9, dplaces); BigNumber.Mul(tmp9, BN_lc_log10R, tmp8); BigNumber.Round(tmp8, dst, places); }
static void M_log_solve_cubic(BigNumber nn, BigNumber rr, int places) { BigNumber tmp0, tmp1, tmp2, tmp3, guess; int ii, maxp, tolerance, local_precision; guess = new BigNumber(); tmp0 = new BigNumber(); tmp1 = new BigNumber(); tmp2 = new BigNumber(); tmp3 = new BigNumber(); BigNumber.M_get_log_guess(nn, guess); tolerance = -(places + 4); maxp = places + 16; local_precision = 18; ii = 0; while (true) { BigNumber.Exp(guess, tmp1, local_precision); BigNumber.Sub(tmp1, nn, tmp3); BigNumber.Add(tmp1, nn, tmp2); BigNumber.Div(tmp3, tmp2, tmp1, local_precision); BigNumber.Mul(BigNumber.Two, tmp1, tmp0); BigNumber.Sub(guess, tmp0, tmp3); if (ii != 0) { if (((3 * tmp0.exponent) < tolerance) || (tmp0.signum == 0)) { break; } } BigNumber.Round(tmp3, guess, local_precision); local_precision *= 3; if (local_precision > maxp) { local_precision = maxp; } ii = 1; } BigNumber.Round(tmp3, rr, places); }
/****************************************************************************/ /* * Calculate PI using the AGM (Arithmetic-Geometric Mean) * * Init : A0 = 1 * B0 = 1 / sqrt(2) * Sum = 1 * * Iterate: n = 1... * * * A = 0.5 * [ A + B ] * n n-1 n-1 * * * B = sqrt [ A * B ] * n n-1 n-1 * * * C = 0.5 * [ A - B ] * n n-1 n-1 * * * 2 n+1 * Sum = Sum - C * 2 * n * * * At the end when C is 'small enough' : * n * * 2 * PI = 4 * A / Sum * n+1 * * -OR- * * 2 * PI = ( A + B ) / Sum * n n * */ static private void CalculatePiAGM(BigNumber outv, int places) { int dplaces, nn; BigNumber tmp1 = new BigNumber(); BigNumber tmp2 = new BigNumber(); BigNumber a0 = new BigNumber(); BigNumber b0 = new BigNumber(); BigNumber c0 = new BigNumber(); BigNumber a1 = new BigNumber(); BigNumber b1 = new BigNumber(); BigNumber sum = new BigNumber(); BigNumber pow_2 = new BigNumber(); dplaces = places + 16; BigNumber.Copy(BigNumber.One, a0); BigNumber.Copy(BigNumber.One, sum); BigNumber.Copy(BigNumber.Four, pow_2); BigNumber.Sqrt(BigNumber.BN_OneHalf, b0, dplaces); while (true) { BigNumber.Add(a0, b0, tmp1); BigNumber.Mul(tmp1, BigNumber.BN_OneHalf, a1); BigNumber.Mul(a0, b0, tmp1); BigNumber.Sqrt(tmp1, b1, dplaces); BigNumber.Sub(a0, b0, tmp1); BigNumber.Mul(BigNumber.BN_OneHalf, tmp1, c0); BigNumber.Mul(c0, c0, tmp1); BigNumber.Mul(tmp1, pow_2, tmp2); BigNumber.Sub(sum, tmp2, tmp1); BigNumber.Round(tmp1, sum, dplaces); nn = -4 * c0.exponent; if (nn >= dplaces) { break; } BigNumber.Copy(a1, a0); BigNumber.Copy(b1, b0); BigNumber.Mul(pow_2, BigNumber.Two, tmp1); BigNumber.Copy(tmp1, pow_2); } BigNumber.Add(a1, b1, tmp1); BigNumber.Mul(tmp1, tmp1, tmp2); BigNumber.Div(tmp2, sum, tmp1, dplaces); BigNumber.Round(tmp1, outv, places); }
static public void RoundFix(BigNumber src, BigNumber dst, int places) { string srcStr = src.ToFullString(); int dotIndex = srcStr.IndexOf("."); if (dotIndex >= 0) { BigNumber.Round(src, dst, dotIndex + places - 1); } else { } }
/****************************************************************************/ /* * calculate log (1 + x) with the following series: * * x * y = ----- ( |y| < 1 ) * x + 2 * * * [ 1 + y ] y^3 y^5 y^7 * log [-------] = 2 * [ y + --- + --- + --- ... ] * [ 1 - y ] 3 5 7 * */ static void M_log_near_1(BigNumber xx, BigNumber rr, int places) { BigNumber tmp0, tmp1, tmp2, tmpS, term; int tolerance, dplaces, local_precision; long m1; tmp0 = new BigNumber(); tmp1 = new BigNumber(); tmp2 = new BigNumber(); tmpS = new BigNumber(); term = new BigNumber(); tolerance = xx.exponent - (places + 6); dplaces = (places + 12) - xx.exponent; BigNumber.Add(xx, BigNumber.Two, tmp0); BigNumber.Div(xx, tmp0, tmpS, (dplaces + 6)); BigNumber.Copy(tmpS, term); BigNumber.Mul(tmpS, tmpS, tmp0); BigNumber.Round(tmp0, tmp2, (dplaces + 6)); m1 = 3L; while (true) { BigNumber.Mul(term, tmp2, tmp0); if ((tmp0.exponent < tolerance) || (tmp0.signum == 0)) { break; } local_precision = dplaces + tmp0.exponent; if (local_precision < 20) { local_precision = 20; } BigNumber.SetFromLong(tmp1, m1); BigNumber.Round(tmp0, term, local_precision); BigNumber.Div(term, tmp1, tmp0, local_precision); BigNumber.Add(tmpS, tmp0, tmp1); BigNumber.Copy(tmp1, tmpS); m1 += 2; } BigNumber.Mul(BigNumber.Two, tmpS, tmp0); BigNumber.Round(tmp0, rr, places); }
static private void Exp(BigNumber src, BigNumber dst, int places) { BigNumber A = 0, B = 0, C = 0; int dplaces, nn = 0, ii = 0; if (src.signum == 0) { BigNumber.Copy(BigNumber.One, dst); return; } if (src.exponent <= -3) { M_raw_exp(src, C, (places + 6)); BigNumber.Round(C, dst, places); return; } if (M_exp_compute_nn(ref nn, A, src) != 0) { throw new BigNumberException("'Exp', Input too large, Overflow"); } dplaces = places + 8; BigNumber.CheckLogPlaces(dplaces); BigNumber.Mul(A, BN_lc_log2, B); BigNumber.Sub(src, B, A); while (true) { if (A.signum != 0) { if (A.exponent == 0) { break; } } if (A.signum >= 0) { nn++; BigNumber.Sub(A, BN_lc_log2, B); BigNumber.Copy(B, A); } else { nn--; BigNumber.Add(A, BN_lc_log2, B); BigNumber.Copy(B, A); } } BigNumber.Mul(A, BN_exp_512R, C); M_raw_exp(C, B, dplaces); ii = 9; while (true) { BigNumber.Mul(B, B, C); BigNumber.Round(C, B, dplaces); if (--ii == 0) { break; } } BigNumber.IntPow(dplaces, BigNumber.Two, nn, A); BigNumber.Mul(A, B, C); BigNumber.Round(C, dst, places); }
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); } }
/****************************************************************************/ /* * 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 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); }
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 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); }