//■BigNumber // // (1) textBox1にAの値、textBox2にBの値を入れてそれぞれのボタンを押すと // 演算が実行されtextBox3に結果が入ります。 // (2) textBox4に計算桁数を入れ、button13をクリックすると // πの値を計算してtextBox3に値が入ります。 // (3) button15をクリックすると自然対数の底eを計算します。 // なお、計算誤差を考慮して計算する余裕桁を // textBox6で指定できるようにしています。 // (4) button14をクリックすると10桁ずつ桁を分離して表示します。 // この際の先頭桁位置をtextBox5で指定します。 // (5) button16をクリックするとtextBox3に表示されている // 数字の出現頻度を計算します。 // (6) Formには、textBox1〜6、button1〜16を貼り付け、 // ボタンにはそれぞれClickイベントハンドラを割り当ててください。 // textBox3のMultiLineプロパティをTrueにしてください。 // using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq;// C#2005以前のバージョンではこれを削除 using System.Text; using System.Windows.Forms; using BigNumber; namespace BigNumber { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private BigNumber getA() { return new BigNumber(textBox1.Text); } private BigNumber getB() { return new BigNumber(textBox2.Text); } private void button1_Click(object sender, EventArgs e) { textBox3.Text = (getA() + getB()).ToString(); } private void button2_Click(object sender, EventArgs e) { textBox3.Text = (getA() - getB()).ToString(); } private void button3_Click(object sender, EventArgs e) { textBox3.Text =( -getA()).ToString(); } private void button4_Click(object sender, EventArgs e) { textBox3.Text = (getA() * getB()).ToString(); } private void button5_Click(object sender, EventArgs e) { textBox3.Text = (getA() / getB()).ToString(); } private void button6_Click(object sender, EventArgs e) { textBox3.Text = (getA() % getB()).ToString(); } private void button7_Click(object sender, EventArgs e) { textBox3.Text = (getA() == getB()).ToString(); } private void button8_Click(object sender, EventArgs e) { textBox3.Text = (getA() != getB()).ToString(); } private void button9_Click(object sender, EventArgs e) { textBox3.Text = (getA() > getB()).ToString(); } private void button10_Click(object sender, EventArgs e) { textBox3.Text = (getA()>= getB()).ToString(); } private void button11_Click(object sender, EventArgs e) { textBox3.Text = (getA() < getB()).ToString(); } private void button12_Click(object sender, EventArgs e) { textBox3.Text = (getA() <= getB()).ToString(); } private void button13_Click(object sender, EventArgs e)//円周率πの計算 { int K = (int.Parse(textBox6.Text) + 1) / 2; if (K < 1) K = 1; int N = int.Parse(textBox4.Text) / 2; if (N <= 5) MessageBox.Show("桁数が小さすぎます。"); else textBox3.Text = BigNumber.compPi(N+K).ToString(); } private void button14_Click(object sender, EventArgs e)//桁分割表示 { int Loop = int.Parse(textBox4.Text); int ist = int.Parse(textBox5.Text); string S = textBox3.Text, R = ""; if (S.Length < Loop) Loop = S.Length; for (int i = ist, k=1; i < Loop; i += 10, k++) { if (((k-1) % 5) == 0) R += "("+i.ToString("0000")+") : "; int N = 10; if ((S.Length - i) < N) N = S.Length - i; R += S.Substring(i, N) + " "; if ((k % 5)== 0) R += "\r\n"; } textBox3.Text = R; } private void button15_Click(object sender, EventArgs e)//ネイピア数e(自然対数の底)の計算 { int K = (int.Parse(textBox6.Text) + 1) / 2; if (K < 1) K = 1; int N = int.Parse(textBox4.Text) / 2; if (N <= 5) MessageBox.Show("桁数が小さすぎます。"); else textBox3.Text = BigNumber.compE(N+K).ToString(); } private void button16_Click(object sender, EventArgs e)//数字出現頻度表示 { int[] Freq = new int[10]; int k; string S0 = "0123456789", Str = textBox3.Text; for (int i = 0; i < Str.Length; i++) if((k = S0.IndexOf(Str.Substring(i, 1)))>=0) Freq[k]++; Str = ""; for (int i = 0; i < 10; i++) Str = Str + i + "(" + Freq[i] + ") "; MessageBox.Show(Str); } } public class BigBig { public BigNumber Q, R; public BigBig(BigNumber quotient, BigNumber remainder) { Q = quotient; R = remainder; } } public class BigNumber { public Boolean sign; public short[] number; public BigNumber(int V)//整数値をBigNumberに変換 { sign = false; int LL = V; if(LL==0)number=new short[0]; else { if(LL<0){ sign=true;LL = - LL; } int K = ((int)Math.Log(LL, 100)) + 1; number = new short[K]; for (int i = 0; i < K; i++, LL /=100) number[i] =(short)( LL % 100); } } public BigNumber(bool s, short[] num,int N)//配列値をBigNumberとする { sign = s; number = new short[N]; for(int i=0;i= 0) s = c+s; } } int len=(s.Length+1)/2; short[] num=new short[len]; for (int i = 0; i < s.Length; i += 2) { string c=s.Substring(i,1); if((i+2)<=s.Length) c = s.Substring(i+1,1)+c; num[i/2] = short.Parse(c); } int k; for (k = len - 1; k >= 0; k--) if (num[k] != 0) break; number = new short[k + 1]; for (int i = 0; i <= k; i++) number[i] = num[i]; } public override string ToString()//BigNumberを文字列に変換 { int Len=number.Length; if (Len == 0) return "0"; string S = ""; if (sign) S = "-"; S += number[Len - 1].ToString(); for (int i = Len - 2; i >= 0; i--) S += number[i].ToString("00"); return S; } public BigNumber omit()//上位の0を省略する。 { int N = number.Length; if(N==0)return new BigNumber(0); for (int i = N - 1; i >= 0; i-- ) if (number[i] != 0) return new BigNumber(sign, number, i + 1); return new BigNumber(0); } public BigNumber addMini(short dt) // 0〜99を加算 { int N=number.Length; if (N == 0) return new BigNumber((int)dt); short[] num = new short[N + 1]; short dt2 = (short)(number[0] + dt); num[0]=(short)(dt2 % 100); for (int i = 1; i < N; i++) { dt2 /= 100; dt2 += number[i]; num[i]=(short)(dt2 % 100); } num[N] = (short)(dt2 / 100); if(num[N]!=0) N=N+1; return new BigNumber(sign, num, N); } public BigNumber addAbs(BigNumber dt) // 絶対値の加算 { int N1=number.Length; if (N1 == 0) return dt; int N2 = dt.number.Length; if (N2 == 0) return new BigNumber(sign, number, N1); int N = N1; if (N < N2) N = N2; short[] num = new short[N + 1]; short dt2 = (short)(number[0] + dt.number[0]); num[0] = (short)(dt2 % 100); for (int i = 1; i < N; i++) { dt2 /= 100; if (i < N1) dt2 += number[i]; if (i < N2) dt2 += dt.number[i]; num[i] = (short)(dt2 % 100); } num[N] = (short)(dt2 / 100); if (num[N] != 0) N = N + 1; return new BigNumber(sign, num, N); } public BigNumber subAbs(BigNumber dt) // 絶対値の減算(引かれる値の方が大きいことを前提) { int N1 = number.Length; int N2 = dt.number.Length; if (N1 == 0) return new BigNumber(!dt.sign,dt.number,dt.number.Length); if (N2 == 0) return new BigNumber(sign, number, N1); int N = N1; short[] num = new short[N]; short T = 0; for (int i = 0; i < N2; i++){ T =(short) (number[i] - dt.number[i] - T); if (T >= 0){ num[i] = T; T = 0; } else { num[i] = (short)(T + 100); T = 1;} } for (int i = N2; i < N1; i++){ T = (short)(number[i] - T); if (T >= 0){ num[i] = T; T = 0;} else { num[i] = (short)(T + 100); T = 1;} } BigNumber C=new BigNumber(sign,num,N); return C.omit(); } public int compareAbs(BigNumber dt) // 絶対値の大きさの比較 { int N1 = number.Length; int N2 = dt.number.Length; if (N1 == 0 && N2 == 0) return 0; if (N1 > N2) return 1; else if (N1 < N2) return -1; else{ for (int i = N1-1; i >= 0; i--) if (number[i] > dt.number[i]) return 1; else if (number[i] < dt.number[i]) return -1; return 0; } } public BigNumber multMini(short dt) // 0〜99を乗算 { int N = number.Length; if (N == 0 || dt==0) return new BigNumber(0); short[] num = new short[N + 1]; int T0 = 0; for (int i = 0; i < N; i++, T0/=100){ T0=number[i]*dt+T0; num[i] = (short)(T0 % 100); } num[N] = (short)T0; if (num[N] != 0) N = N + 1; return new BigNumber(sign, num, N); } public BigNumber multAbs(BigNumber dt) // BigNumber同士の乗算 { int i, j, N1 = number.Length, N2 = dt.number.Length; if (N1 == 0 || N2 == 0) return new BigNumber(0); int N = N1 + N2; short[] num = new short[N+1]; for (i = 0; i < num.Length; i++) num[i] = 0; for (j = 0; j < N2; j++){ int U = dt.number[j]; if (U != 0){ int T0 = 0; for (i = 0; i < N1; i++) { T0 = num[i+j] + number[i] * U + T0; num[i+j] = (short)(T0 % 100); T0 = T0 / 100; } i = N1 + j; T0 = num[i] + T0; while (T0 >= 100){ num[i] = (short)(T0 - 100); i = i + 1;T0=num[i]+1; } num[i] = (short)T0; } } BigNumber X = new BigNumber(sign, num, N); return X.omit(); } public int divMiniProc(int N, short[] num, short dt)// 0〜99で除算の基本処理 { int T0 = 0; for (int i = N - 1; i >= 0; i--){ T0 = T0 * 100 + number[i]; num[i] = (short)(T0 / dt); T0 = T0 - num[i] * dt; } return T0; } public BigBig divMini(short dt) // 0〜99で除算 { int N = number.Length; if (dt == 0) MessageBox.Show("0で除算しました"); if (N == 0 || dt == 0) return new BigBig(new BigNumber(0),new BigNumber(0)); short[] num = new short[N]; int T0= divMiniProc(N, num, dt); return new BigBig(new BigNumber(sign, num, N), new BigNumber((short)T0)); } public short modMini(short dt) // 0〜99で除算 { if (dt == 0) MessageBox.Show("0で除算しました"); int N = number.Length; if (N == 0 || dt == 0) return 0; short[] num = new short[N]; int T0 = divMiniProc(N, num, dt); return (short)T0; } public BigNumber divMiniQ(short dt)// 0〜99で除算した剰余 { if (dt == 0) MessageBox.Show("0で除算しました"); int N = number.Length; if (N == 0 || dt == 0) return new BigNumber(0); short[] num = new short[N]; int T0 = divMiniProc(N, num, dt); return (new BigNumber(sign, num, N)).omit(); } public int quot(int V, BigNumber dt, short[] C, short[] R, int j) { // 商×除数 ≦ 被除数となるよう商の値を調整する. int i, k, T, N2 = dt.number.Length, Q1 = V / dt.number[N2 - 1]; bool lessThan = true; while (lessThan) { for (i = 0; i <= N2; i++) C[i] = 0; T = 0; for (i = 0; i < N2; i++){ T = dt.number[i] * Q1 + T; C[i] = (short)(T % 100); T /= 100; } C[N2] = (short)T; k = j + N2; lessThan = false; for (i = N2; i >= 0; i--, k--) if (R[k] > C[i]) break; else if (R[k] < C[i]){lessThan = true; break;} if (lessThan) Q1--; } return Q1; } public void divProc(int N,int N2,BigNumber dt,short[]C, short[] R, short[] Q) { // 除算の基本処理 int i, j, Q1, T, k = N2, jk = N - 1, V = 0; for (j = N - N2; j >= 0; j--) { V = V * 100 + R[N2 + j - 1]; if (V >= dt.number[N2 - 1]){ Q1 = quot(V, dt, C, R, j); T = 0; k = j; for (i = 0; i <= N2; i++, k++){ T = (short)(R[k] - C[i] - T); if (T >= 0) { R[k] = (short)T; T = 0; } else { R[k] = (short)(T + 100); T = 1;} } V = 0; for (i = N; i >= j + N2 - 1; i--) V = V * 100 + R[i]; Q[j] = (short)Q1; } } } public void moveShort(int N, short[] R)//配列の移動 { for (int i = 0; i < N; i++) R[i] =number[i];} public BigBig divAbs(BigNumber dt) // BigNumberで除算 { int N = number.Length; int N2 = dt.number.Length; if ( N2== 0) MessageBox.Show("0で除算しました"); if (N == 0 || N2 == 0) return new BigBig(new BigNumber(0), new BigNumber(0)); if (N2 == 1) return divMini(dt.number[0]); int flag = compareAbs(dt); if (flag == 0) return new BigBig(new BigNumber(1), new BigNumber(0)); else if (flag < 0) return new BigBig(new BigNumber(0), dt); short[] R=new short[N+1]; short[] C=new short[N2+1]; int NR = N - N2+1; short[] Q = new short[NR]; moveShort(N, R); R[N]=0; divProc(N, N2, dt, C, R, Q); BigNumber QQ = new BigNumber(false, Q, NR); BigNumber RR = new BigNumber(false, R, N); return new BigBig(QQ.omit(), RR.omit()); } public BigNumber divAbsQ(BigNumber dt) // BigNumberで除算 { int N = number.Length; int N2 = dt.number.Length; if (N2 == 0) MessageBox.Show("0で除算しました"); if (N == 0 || N2 == 0) return new BigNumber(0); if (N2 == 1) return divMiniQ(dt.number[0]); int flag = compareAbs(dt); if (flag == 0) return new BigNumber(1); else if (flag < 0) return new BigNumber(0); short[] R = new short[N + 1]; short[] C = new short[N2 + 1]; int NR = N - N2 + 1; short[] Q = new short[NR]; moveShort(N, R); R[N] = 0; divProc(N, N2, dt, C, R, Q); return (new BigNumber(false, Q, NR)).omit(); } public BigNumber modAbs(BigNumber dt) // BigNumberで除算した剰余 { int N = number.Length; int N2 = dt.number.Length; if (N2 == 0) MessageBox.Show("0で除算しました"); if (N == 0 || N2 == 0) return new BigNumber(0); if (N2 == 1) return new BigNumber(modMini(dt.number[0])); int flag = compareAbs(dt); if (flag == 0) return new BigNumber(0); else if (flag < 0) return dt; short[] R = new short[N + 1]; short[] C = new short[N2 + 1]; int NR = N - N2 + 1; short[] Q = new short[NR]; moveShort(N, R); R[N] = 0; divProc(N, N2, dt, C, R, Q); return (new BigNumber(false, R, N)).omit(); } public static BigNumber operator +(BigNumber A, BigNumber B)// A + B { BigNumber C; if (A.sign == B.sign) { C = A.addAbs(B); C.sign = A.sign; } else { int check = A.compareAbs(B); if (check == 0) C = new BigNumber(0); else if (check > 0) { C = A.subAbs(B); C.sign = A.sign; } else { C = B.subAbs(A); C.sign = B.sign; } } return C; } public static BigNumber operator +(int A, BigNumber B)// A + B { return (new BigNumber(A)) + B;} public static BigNumber operator +(BigNumber A, int B)// A + B { return A + (new BigNumber(B));} public static BigNumber operator +(BigNumber A)// +A { return A;} public static BigNumber operator -(BigNumber A, BigNumber B)// A - B { BigNumber C; if (A.sign == B.sign) { int check = A.compareAbs(B); if (check == 0) C = new BigNumber(0); else if (check > 0) { C = A.subAbs(B); C.sign = A.sign; } else { C = B.subAbs(A); C.sign = !A.sign; } } else { C = A.addAbs(B); C.sign = A.sign; } return C; } public static BigNumber operator -(int A, BigNumber B) { return (new BigNumber(A)) - B; } public static BigNumber operator -(BigNumber A, int B) { return A - (new BigNumber(B));} public static BigNumber operator -(BigNumber A)// -A { if (A.number.Length == 0) return new BigNumber(0); return new BigNumber(!A.sign, A.number, A.number.Length); } public static BigNumber operator *(BigNumber A, BigNumber B)// A * B { BigNumber C; if (A.compareAbs(B) >= 0) C = A.multAbs(B); else C = B.multAbs(A); C.sign = !(A.sign == B.sign); return C; } public static BigNumber operator *(int A, BigNumber B) { return (new BigNumber(A)) * B; } public static BigNumber operator *(BigNumber A, int B) { return A * (new BigNumber(B)); } public static BigNumber operator /(BigNumber A, BigNumber B)// A / B { BigNumber QR = A.divAbsQ(B); QR.sign = !(A.sign == B.sign);return QR;} public static BigNumber operator /(int A, BigNumber B) { return (new BigNumber(A)) / B; } public static BigNumber operator /(BigNumber A, int B) { return A / (new BigNumber(B)); } public static BigNumber operator %(BigNumber A, BigNumber B) // A % B { BigNumber QR = A.modAbs(B); QR.sign = !(A.sign == B.sign); return QR;} public static BigNumber operator %(int A, BigNumber B) { return (new BigNumber(A)) % B; } public static BigNumber operator %(BigNumber A, int B) { return A % (new BigNumber(B)); } public static bool operator ==(BigNumber A, BigNumber B)// A==B { if (A.number.Length == 0) return (B.number.Length == 0); else { if ((B.number.Length == 0) || (A.sign != B.sign)) return false; return (A.compareAbs(B) == 0); } } public static bool operator ==(int A, BigNumber B) { return (new BigNumber(A)) == B; } public static bool operator ==(BigNumber A, int B) { return A == (new BigNumber(B)); } public static bool operator !=(BigNumber A, BigNumber B)// != { return !(A == B);} public static bool operator !=(int A, BigNumber B) { return (new BigNumber(A)) != B; } public static bool operator !=(BigNumber A, int B) { return A != (new BigNumber(B));} public static bool operator >(BigNumber A, BigNumber B)// > { if (A.number.Length == 0 && B.number.Length == 0) return false; else if (A.number.Length == 0) return B.sign; // A = 0 のとき B が負ならばtrue else if (B.number.Length == 0) return !A.sign; // B = 0 のとき A が正ならばtrue else if (A.sign && B.sign) return (A.compareAbs(B) < 0);// 両方が負ならば絶対値小が大 else if (A.sign) return false; else return ((B.sign) || (A.compareAbs(B) > 0));// 両方が正のとき絶対値大が大 } public static bool operator >(int A, BigNumber B) { return ((new BigNumber(A) > B)); } public static bool operator >(BigNumber A, int B) { return (A > (new BigNumber(B))); } public static bool operator <(BigNumber A, BigNumber B)// < { if (A.number.Length == 0) return !((B.number.Length == 0) || B.sign); else if (B.number.Length == 0) return A.sign;     // B = 0,A<0のとき else if (A.sign && B.sign) return(A.compareAbs(B) > 0);// ABともに負のとき else if (A.sign) return true; // A < 0 & B > 0 else if (B.sign) return false; // A > 0 & B < 0 else return (A.compareAbs(B) < 0); // ABともに正 } public static bool operator <(int A, BigNumber B) { return ((new BigNumber(A) < B)); } public static bool operator <(BigNumber A, int B) { return (A < (new BigNumber(B))); } public static bool operator >=(BigNumber A, BigNumber B)// >= { return !(A< B); } public static bool operator >=(int A, BigNumber B) { return ((new BigNumber(A) >= B)); } public static bool operator >=(BigNumber A, int B) { return (A >= (new BigNumber(B))); } public static bool operator <=(BigNumber A, BigNumber B)// <= { return !(A> B); } public static bool operator <=(int A, BigNumber B) { return ((new BigNumber(A) <= B)); } public static bool operator <=(BigNumber A, int B) { return (A <= (new BigNumber(B))); } public static BigNumber compPi(int MX)//円周率πの計算 { int MXX = MX + 1; BigNumber Pi = new BigNumber(0), T = new BigNumber(false, MXX, 16); T = T.divMiniQ(5); BigNumber K = new BigNumber(1), U = T; do { Pi = Pi.addAbs(U); T = T.divMiniQ(25); K = K.addMini(2); U = T.divAbsQ(K); Pi = Pi.subAbs(U); T = T.divMiniQ(25); K = K.addMini(2); U = T.divAbsQ(K); } while (U.number.Length != 0); T = new BigNumber(false, MXX, 4); BigNumber N239 = new BigNumber(239), N239sq = N239.multAbs(N239); T = T.divAbsQ(N239); K = new BigNumber(1); U = T; do{ Pi = Pi.subAbs(U); T = T.divAbsQ(N239sq); K = K.addMini(2); U = T.divAbsQ(K); Pi = Pi.addAbs(U); T = T.divAbsQ(N239sq); K = K.addMini(2); U = T.divAbsQ(K); } while (U.number.Length != 0); return Pi; } public static BigNumber compE(int MX)//ネイピア数e(自然対数の底)計算 { BigNumber E = new BigNumber(false, MX + 1, 1), K = new BigNumber(1); BigNumber T = E; do{ E = E.addAbs(T); K = K.addMini(1); T = T.divAbsQ(K);} while (T.number.Length != 0); return E; } public override bool Equals(object obj) { return base.Equals(obj); } public override int GetHashCode() { return base.GetHashCode();} } }