2012/04/01(日)C# で BigInteger
とりあえず10進数で2300桁ぐらい扱える全然BigじゃないBigInt。負の値は扱えない。
256のとこを大きくしたら扱える桁数が増える。
割り算と剰余演算子作るのめんどくさくて作ってないけど、
たいてい必要になるのってその辺なんだよなー。もじゅろ10億7とかさー。
というわけで、longのもじゅろだけはとれるよーにしといた。
実戦で使える速度が出るかどうかは未検証。
まぁでもそういう問題は、たぶん、計算量的に無理なようにできてるでしょうね。
public class BigInt : IComparable<BigInt>, IEquatable<BigInt> { long[] value = new long[256]; const long M = 1000000000L; const int K = 9; // Mの0が9個ある public BigInt() { } public BigInt(long l) { value[0] = l; value = (One * this).value; } public static BigInt Parse(string s) { BigInt ret = new BigInt(); for (int i = 0; i < (s.Length + K - 1) / K; i++) ret.value[i] = long.Parse(s.Substring(Math.Max(0, s.Length - (i + 1) * K), Math.Min(K, s.Length - i * K))); return ret; } public override string ToString() { Array.Reverse(value); string s = string.Join("", Array.ConvertAll(value, delegate(long l) { return l.ToString("000000000"); })); int i = s.IndexOfAny(new char[] { '1', '2', '3', '4', '5', '6', '7', '8', '9', }); Array.Reverse(value); return i != -1 ? s.Remove(0, i) : "0"; } public static BigInt operator +(BigInt a, BigInt b) { BigInt ret = new BigInt(); long carry = 0; for (int i = 0; i < ret.value.Length; i++) { long t = a.value[i] + b.value[i] + carry; if (t >= M) { ret.value[i] = t - M; carry = 1; } else { ret.value[i] = t; carry = 0; } } return ret; } public static BigInt operator -(BigInt a, BigInt b) { BigInt ret = new BigInt(); long carry = 1; for (int i = 0; i < ret.value.Length; i++) { long t = a.value[i] - b.value[i] - 1 + carry + M; if (t >= M) { ret.value[i] = t - M; carry = 1; } else { ret.value[i] = t; carry = 0; } } return ret; } public static BigInt operator *(BigInt a, BigInt b) { BigInt ret = new BigInt(); for (int j = 0; j < b.value.Length; j++) { if (b.value[j] == 0) continue; // たいていbのがちっさいはず for (int i = 0; i < a.value.Length; i++) { long carry = 0; if (i + j >= ret.value.Length) continue; long t = ret.value[i + j] + a.value[i] * b.value[j] + carry; ret.value[i + j] = t % M; carry = t / M; } } return ret; } //public static BigInt operator /(BigInt a, BigInt b) { throw new NotImplementedException(/*_*/); } //public static BigInt operator %(BigInt a, BigInt b) { throw new NotImplementedException(/*_*/); } public static BigInt operator /(BigInt a, long b) { BigInt ret = new BigInt(); long carry = 0; for (int i = a.value.Length - 1; i >= 0; i--) { long t = carry * M + a.value[i]; ret.value[i] = t / b; carry = t % b; } return ret; } public static long operator %(BigInt a, long b) { long ret = 0; for (int i = a.value.Length - 1; i >= 0; i--) ret = (ret * M + a.value[i]) % b; return ret; } public static bool operator ==(BigInt a, BigInt b) { return a.CompareTo(b) == 0; } public static bool operator !=(BigInt a, BigInt b) { return a.CompareTo(b) != 0; } public static bool operator <(BigInt a, BigInt b) { return a.CompareTo(b) < 0; } public static bool operator >(BigInt a, BigInt b) { return a.CompareTo(b) > 0; } public static bool operator <=(BigInt a, BigInt b) { return a.CompareTo(b) <= 0; } public static bool operator >=(BigInt a, BigInt b) { return a.CompareTo(b) >= 0; } public static readonly BigInt Zero = BigInt.Parse("0"); public static readonly BigInt One = BigInt.Parse("1"); public int CompareTo(BigInt other) { for (int i = value.Length - 1; i >= 0; i--) { int r = value[i].CompareTo(other.value[i]); if (r != 0) return r; } return 0; } public override bool Equals(object obj) { if (obj is BigInt) return Equals((BigInt)obj); else return false; } public override int GetHashCode() { long r = 0; for (int i = 0; i < value.Length; i++) r ^= value[i]; return (int)(r >> 32 ^ r); } public bool Equals(BigInt other) { return this == other; } } public class Program { static void Main() { BigInt a = BigInt.Parse("12345678987654321"); BigInt b = BigInt.Parse("12345678987654321"); Console.WriteLine(a.ToString()); Console.WriteLine((a + b).ToString()); Console.WriteLine((a - b).ToString()); Console.WriteLine((a * b).ToString()); Console.WriteLine((a == b).ToString()); Console.WriteLine((a % 9).ToString()); } }
.NET 4が使えるなら、標準のBigIntegerを使いたまえ
っていうか実装されるのおせーよ