public MainWindow() { InitializeComponent(); calc.times = new int[3]; //初始化,存1、2、4、根号2的大数表示 calc.one = new bigNum("1"); calc.two = new bigNum("2"); calc.four = new bigNum("4"); calc.sqrt2 = bigNum.sqrt(2); //calc.sqrt2.show(); /* * 计算ln2 */ bigNum sqrt2_1 = calc.sqrt2 - calc.one; calc.ln2 = new bigNum("0"); bigNum an = new bigNum(sqrt2_1); for (int i = 1; i <= 300; ++i) { calc.ln2 = calc.ln2 + an / (new bigNum(i.ToString())); an = an * sqrt2_1; an.neg = (i % 2 == 1 ? true : false); } calc.ln2 = calc.ln2 * calc.two; //calc.ln2.show(); }
/* * 大数数字加法 */ private static bigNum plus(bigNum b1, bigNum b2) { bigNum bn1 = new bigNum(b1), bn2 = new bigNum(b2), ans = new bigNum(); if (bn1.dot > bn2.dot) { for (int i = bn2.cnt - 1; i >= 0; --i) { bn2.num[i + bn1.dot - bn2.dot] = bn2.num[i]; bn2.num[i] = 0; } bn2.cnt += bn1.dot - bn2.dot; bn2.dot = bn1.dot; } else if (bn1.dot < bn2.dot) { for (int i = bn1.cnt - 1; i >= 0; --i) { bn1.num[i + bn2.dot - bn1.dot] = bn1.num[i]; bn1.num[i] = 0; } bn1.cnt += bn2.dot - bn1.dot; bn1.dot = bn2.dot; } else { } ans.cnt = bn1.cnt > bn2.cnt ? bn1.cnt : bn2.cnt; ans.dot = bn1.dot; for (int i = 0; i < ans.cnt; ++i) { ans.num[i] = bn1.num[i] + bn2.num[i]; } //进位 for (int i = 0; i < ans.cnt; ++i) { if (ans.num[i] >= mod) { ans.num[i + 1] += ans.num[i] / mod; ans.num[i] %= mod; if (i == ans.cnt - 1) { ++ans.cnt; } } } if (ans.cnt > maxlen) { int delta = ans.cnt - maxlen; for (int i = 0; i < maxlen; ++i) { ans.num[i] = ans.num[i + delta]; ans.num[i + delta] = 0; } ans.dot -= delta; ans.cnt = maxlen; } return(ans); }
/* * 大数除法 */ public static bigNum operator /(bigNum b1, bigNum b2) { bigNum ans = new bigNum("0"); bigNum bn1 = new bigNum(b1), bn2 = new bigNum(b2); int[] num_a = bn1.num, num_b = bn2.num; int len1 = bn1.cnt, len2 = bn2.cnt; for (int i = len1 - 1; i >= 0; --i) { num_a[i + maxlen * 2 - len1] = num_a[i]; num_a[i] = 0; } len1 = maxlen * 2; int nTimes = len1 - len2; for (int i = len2 - 1; i >= 0; --i) { num_b[i + nTimes] = num_b[i]; num_b[i] = 0; } len2 = len1; int nTemp; for (int i = 0; i <= nTimes; ++i) { while ((nTemp = SubStract(num_a, num_b, len1, len2, i)) >= 0) { len1 = nTemp; ans.num[nTimes - i]++; } if (len1 == len2 - i && num_a[len1 - 1] == 0) { len1--; } } ans.dot = 2 * maxlen - (bn1.cnt - bn1.dot) - bn2.dot; ans.cnt = len2; while (ans.num[ans.cnt - 1] == 0 && ans.cnt > ans.dot + 1) { ans.cnt--; } if (ans.cnt > maxlen) { int delta = ans.cnt - maxlen; for (int i = 0; i < maxlen; ++i) { ans.num[i] = ans.num[i + delta]; ans.num[i + delta] = 0; } ans.dot -= delta; ans.cnt = maxlen; } ans.neg = bn1.neg ^ bn2.neg; return(ans); }
public bigNum(bigNum bn)//由大数初始化 { neg = bn.neg; cnt = bn.cnt; dot = bn.dot; num = new int[1010]; for (int i = 0; i < cnt; ++i) { num[i] = bn.num[i]; } }
/* * 整数开根号 */ public static bigNum sqrt(int xx) { if (xx > 0) { bool flag = false; bigNum x = new bigNum(xx.ToString()); bigNum[] a = new bigNum[2]; a[1] = new bigNum("1"); bigNum delta; bool loop = true; while (loop) { loop = false; if (!flag) { a[0] = (a[1] + x / a[1]) / calc.two; } else { a[1] = (a[0] + x / a[0]) / calc.two; } flag = !flag; delta = a[1] - a[0]; for (int j = delta.cnt - 1; j >= delta.dot; --j) { if (delta.num[j] != 0) { loop = true; break; } } if (!loop) { for (int j = delta.dot - 1; j >= delta.dot - 500 && j >= 0; --j) { if (delta.num[j] != 0) { loop = true; break; } } } } return(flag ? a[1] : a[0]); } return(new bigNum("0")); }
/* * 根据要求精度四舍五入 */ public bigNum round(bigNum bn, int acc) { bigNum ans = new bigNum(bn); if (ans.dot <= acc) { for (int i = ans.cnt - 1; i >= 0; --i) { ans.num[i + acc - ans.dot] = ans.num[i]; ans.num[i] = 0; } ans.cnt += acc - ans.dot; ans.dot = acc; } else { if (ans.num[ans.dot - acc - 1] >= 5) { ans.num[ans.dot - acc] += 1; } for (int i = ans.dot - acc; i < ans.cnt; ++i) { if (ans.num[i] >= mod) { ans.num[i + 1] += ans.num[i] / mod; ans.num[i] %= mod; if (i == ans.cnt - 1) { ans.cnt++; } } else { break; } } } return(ans); }
/* * 大数乘法 */ public static bigNum operator *(bigNum b1, bigNum b2) { bigNum ans = new bigNum(); for (int i = 0; i < b1.cnt; ++i) { for (int j = 0; j < b2.cnt; ++j) { ans.num[i + j] += b1.num[i] * b2.num[j]; } } ans.cnt = b1.cnt + b2.cnt - 1; ans.dot = b1.dot + b2.dot; for (int i = 0; i < ans.cnt; ++i) { if (ans.num[i] >= mod) { ans.num[i + 1] += ans.num[i] / mod; ans.num[i] %= mod; if (i == ans.cnt - 1) { ++ans.cnt; } } } if (ans.cnt > maxlen) { int delta = ans.cnt - maxlen; for (int i = 0; i < maxlen; ++i) { ans.num[i] = ans.num[i + delta]; ans.num[i + delta] = 0; } ans.dot -= delta; ans.cnt = maxlen; } return(ans); }
/* * 大数带符号减法 */ public static bigNum operator -(bigNum b1, bigNum b2) { bigNum ans = new bigNum(); if ((b1.neg ^ b2.neg))//符号不同,数字相加,符号跟随被减数 { ans = plus(b1, b2); ans.neg = b1.neg; } else//符号相同,数字相减, { if (b1 >= b2) { ans = minus(b1, b2); ans.neg = b1.neg; } else { ans = minus(b2, b1); ans.neg = !b1.neg; } } if (ans.cnt > maxlen) { int delta = ans.cnt - maxlen; for (int i = 0; i < maxlen; ++i) { ans.num[i] = ans.num[i + delta]; ans.num[i + delta] = 0; } ans.dot -= delta; ans.cnt = maxlen; } return(ans); }
/* * 大数数字减法 */ private static bigNum minus(bigNum b1, bigNum b2) { bigNum bn1 = new bigNum(b1), bn2 = new bigNum(b2), ans = new bigNum(); if (bn1.dot > bn2.dot) { for (int i = bn2.cnt - 1; i >= 0; --i) { bn2.num[i + bn1.dot - bn2.dot] = bn2.num[i]; bn2.num[i] = 0; } bn2.cnt += bn1.dot - bn2.dot; bn2.dot = bn1.dot; } else if (bn1.dot < bn2.dot) { for (int i = bn1.cnt - 1; i >= 0; --i) { bn1.num[i + bn2.dot - bn1.dot] = bn1.num[i]; bn1.num[i] = 0; } bn1.cnt += bn2.dot - bn1.dot; bn1.dot = bn2.dot; } else { } ans.cnt = bn1.cnt > bn2.cnt ? bn1.cnt : bn2.cnt; ans.dot = bn1.dot; for (int i = 0; i < ans.cnt; ++i) { ans.num[i] = bn1.num[i] - bn2.num[i]; } //借位 for (int i = 0; i < ans.cnt; ++i) { if (ans.num[i] < 0) { ans.num[i + 1] += ans.num[i] / mod; ans.num[i] %= mod; if (ans.num[i] < 0) { ans.num[i + 1]--; ans.num[i] += mod; } } } while (ans.num[ans.cnt - 1] == 0 && ans.cnt > ans.dot + 1) { ans.cnt--; } if (ans.cnt > maxlen) { int delta = ans.cnt - maxlen; for (int i = 0; i < maxlen; ++i) { ans.num[i] = ans.num[i + delta]; ans.num[i + delta] = 0; } ans.dot -= delta; ans.cnt = maxlen; } return(ans); }
/* * a. Taylor展开(最佳或近似最佳逼近); * b. 数值积分; * c. 非Taylor展开的函数逼近方法(选作); */ private void button_Click(object sender, RoutedEventArgs e) { if (accuracy.Text == "") { MessageBox.Show("请输入精度"); return; } if (num.Text == "") { MessageBox.Show("请输入x"); return; } Stopwatch stopwatch = new Stopwatch(); for (int i = 0; i < accuracy.Text.Length; ++i) { if (accuracy.Text[i] < '0' || accuracy.Text[i] > '9') { MessageBox.Show("精度请输入有效正整数"); return; } } acc = Convert.ToInt32(accuracy.Text); if (acc >= 50) { MessageBox.Show("精度建议小于50"); return; } if (acc < 0) { MessageBox.Show("结果小数位数大于等于0"); return; } int cntdot = 0; for (int i = 0; i < num.Text.Length; ++i) { if (num.Text[i] < '0' || num.Text[i] > '9') { if (num.Text[i] == '.') { cntdot++; if (cntdot > 1) { MessageBox.Show("请输入有效x"); return; } } else { MessageBox.Show("请输入有效x"); return; } } } bigNum input = new bigNum(num.Text); if (input < calc.one) { MessageBox.Show("请输入不小于1的x"); return; } /* * Taylor展开段 */ stopwatch.Reset(); stopwatch.Start(); bigNum halfTaylorAns = calc.halfTaylor(num.Text, acc); halfTaylor.Text = (calc.round(halfTaylorAns, acc)).show(acc); stopwatch.Stop(); halfTaylorTime.Text = stopwatch.ElapsedMilliseconds.ToString() + "ms"; halfTaylorTimes.Text = calc.times[0].ToString(); /* * Romberg数值积分段 */ stopwatch.Reset(); stopwatch.Start(); bigNum rombergAns = calc.romberg(num.Text, acc); romberg.Text = (calc.round(rombergAns, acc)).show(acc); stopwatch.Stop(); rombergTime.Text = stopwatch.ElapsedMilliseconds.ToString() + "ms"; rombergTimes.Text = calc.times[1].ToString(); /* * 有理逼近段 */ stopwatch.Reset(); stopwatch.Start(); bigNum rationalAns = calc.rational(num.Text, acc); rational.Text = (calc.round(rationalAns, acc)).show(acc); stopwatch.Stop(); rationalTime.Text = stopwatch.ElapsedMilliseconds.ToString() + "ms"; rationalTimes.Text = calc.times[2].ToString(); //MessageBox.Show("Done!"); }