/// <summary>开方</summary> static internal BigNumber Sqrt(BigNumber value, int precision) { if (!value.IsPlus) { throw new ExpressionException("只有正数才有开平方运算"); } List <int> div = new List <int>(); int index = 0; int resultIntCount = (value.IntPart.Count + 1) / 2; List <int> result = GetFirstDiv(value, ref div, ref index); div = FirstTry(result, div); div.AddRange(GetNewTwoDiv(value, ref index)); BigCalculate.RemoveStartZero(div); //考虑精度的计算 while (true) { div = TryDiv(div, result); if (result.Count - resultIntCount >= precision) { break; } div.AddRange(GetNewTwoDiv(value, ref index)); BigCalculate.RemoveStartZero(div); } return(new BigNumber(result.GetRange(0, resultIntCount), result.GetRange(resultIntCount, result.Count - resultIntCount), true)); }
/// <summary>第一次用开方尝试</summary> private static List <int> FirstTry(List <int> result, List <int> div) { int tryDiv = BigNumber.Max / 2; int low = 1; int top = BigNumber.Max - 1; //第一位数是1 //第一用平方试商 while (true) { if (BigCalculate.CompareList(new List <int>() { 1 }, div) == 0) { div = BigCalculate.IntMinus(div, new List <int>() { 1 }); result.Add(1); break; } //连9都小了,那么就是9 if (BigCalculate.CompareList(BigCalculate.Multiply(BigNumber.Max - 1, BigNumber.Max - 1), div) == -1) { div = BigCalculate.IntMinus(div, BigCalculate.Multiply(BigNumber.Max - 1, BigNumber.Max - 1)); result.Add(BigNumber.Max - 1); break; } int c = BigCalculate.CompareList(BigCalculate.Multiply(tryDiv, tryDiv), div); //商大了 if (c == -1) { low = tryDiv; tryDiv = (low + top) / 2; } else if (c == 1) //商小了 { top = tryDiv; tryDiv = (low + top) / 2; } else //刚好相等 { div.Clear(); result.Add(tryDiv); break; } if (low + 1 == top) { div = BigCalculate.IntMinus(div, BigCalculate.Multiply(low, low)); result.Add(low); break; } } return(div); }
/// <summary>执行一次试商的运算</summary> /// <param name="div">已经加组的被除数</param> /// <param name="result">已生成的结果</param> static List <int> TryDiv(List <int> div, List <int> result) { int i = BigNumber.Max / 2; int low = 0; int top = BigNumber.Max - 1; //连1都大了,那么商为0,除数不变 if (CompartDiv(1, result, div) == 1) { result.Add(0); return(div); } //连9999都小了 if (CompartDiv(BigNumber.Max - 1, result, div) == -1) { List <int> r = BigCalculate.IntMinus(div, CalDiv(BigNumber.Max - 1, result)); result.Add(BigNumber.Max - 1); return(r); } while (true) { int c = CompartDiv(i, result, div); //商大了 if (c == 1) { top = i; i = (low + top) / 2; } //商小了 else if (c == -1) { low = i; i = (low + top) / 2; } //刚好相等 else { //div.Clear(); result.Add(i); return(new List <int>()); } //已找到合适的商 if (low + 1 == top) { List <int> r = BigCalculate.IntMinus(div, CalDiv(low, result)); result.Add(low); return(r); } } }
/// <summary>计算x(x+20*result)的值</summary> static List <int> CalDiv(int x, List <int> result) { List <int> result20 = BigCalculate.Multiply(new List <int>() { BigNumber.Max * 2 }, result); List <int> add = BigCalculate.IntAdd(new List <int>() { x }, result20, 0); List <int> r = BigCalculate.Multiply(new List <int>() { x }, add); return(r); }
/// <summary>返回0.00001这样的数小数点后、有效数前有几个零</summary> internal int GetPrecision(int value) { if (value == 0) { BigCalculate.RemoveStartZero(IntPart); if (IntPart.Count == 1 && IntPart[0] == 0) { if (DecimalPart.Count == 0) { return(0); } for (int i = 0; i < DecimalPart.Count; i++) { if (DecimalPart[i] != 0) { return(i); } } return(DecimalPart.Count); } return(0); } else { if (IntPart.Count == 1 && IntPart[0] == 1) { if (DecimalPart.Count == 0) { return(0); } for (int i = 0; i < DecimalPart.Count; i++) { if (DecimalPart[i] != 0) { return(i); } } return(DecimalPart.Count); } return(0); } }
/// <summary>识别出一个大数,返回值为这个是不是正数</summary> public static bool GetBigNumber(string text, List <int> intPart, List <int> decimalPart) { ValidateNumber(text); bool isPlus = true; int haveSym = 0; if (text[0] == '-') { isPlus = false; haveSym = 1; } else if (text[0] == '+') { haveSym = 1; } int pointIndex = text.IndexOf('.'); //有小数点 if (pointIndex != -1) { int i = 0; if ((pointIndex - haveSym) % BigNumber.OneCount != 0) { intPart.Add(Convert.ToInt32(text.Substring(haveSym, (pointIndex - haveSym) % BigNumber.OneCount))); } for (; i < (pointIndex - haveSym) / BigNumber.OneCount; i++) { intPart.Add(Convert.ToInt32(text.Substring(haveSym + i * BigNumber.OneCount + (pointIndex - haveSym) % BigNumber.OneCount, BigNumber.OneCount))); } i = pointIndex + 1; while (i < text.Length) { if (text.Length - i >= BigNumber.OneCount) { decimalPart.Add(Convert.ToInt32(text.Substring(i, BigNumber.OneCount))); } else { decimalPart.Add(Convert.ToInt32(text.Substring(i, (text.Length - i) % BigNumber.OneCount).PadRight(BigNumber.OneCount, '0'))); } i += BigNumber.OneCount; } } //没有小数点 else { if ((text.Length - haveSym) % BigNumber.OneCount != 0) { intPart.Add(Convert.ToInt32(text.Substring(haveSym, (text.Length - haveSym) % BigNumber.OneCount))); } for (int i = 0; i < (text.Length - haveSym) / BigNumber.OneCount; i++) { intPart.Add(Convert.ToInt32(text.Substring(haveSym + i * BigNumber.OneCount + (text.Length - haveSym) % BigNumber.OneCount, BigNumber.OneCount))); } } BigCalculate.RemoveStartZero(intPart); if (intPart.Count == 0) { intPart.Add(0); } return(isPlus); }
/// <summary>对除数进行比较</summary> static int CompartDiv(int x, List <int> result, List <int> div) { return(BigCalculate.CompareList(CalDiv(x, result), div)); }
/// <summary>指定精确的除法</summary> public static BigNumber Division(BigNumber dividend, BigNumber divisor, int precision) { return(BigCalculate.Division(dividend, divisor, precision)); }
public static BigNumber operator /(BigNumber a, BigNumber b) { return(BigCalculate.Division(a, b)); }
public static BigNumber operator *(BigNumber a, BigNumber b) { return(BigCalculate.Multiply(a, b)); }
public static BigNumber operator -(BigNumber a, BigNumber b) { return(BigCalculate.Minus(a, b)); }
public static BigNumber operator +(BigNumber a, BigNumber b) { return(BigCalculate.Add(a, b)); }
static int ComparePlus(BigNumber one, BigNumber two) { BigCalculate.RemoveStartZero(one.IntPart); BigCalculate.RemoveStartZero(two.IntPart); int minDecimalLength = one.DecimalPart.Count < two.DecimalPart.Count ? one.DecimalPart.Count : two.DecimalPart.Count; //通过正数的长短比较 if (one.IntPart.Count > two.IntPart.Count) { return(1); } else if (one.IntPart.Count < two.IntPart.Count) { return(-1); } else { //从最高位依次比较 for (int i = 0; i < one.IntPart.Count; i++) { if (one.IntPart[i] > two.IntPart[i]) { return(1); } else if (one.IntPart[i] < two.IntPart[i]) { return(-1); } } //比较小数部分,行判断是否有小数位 if (one.DecimalPart.Count == 0 && two.DecimalPart.Count != 0) { return(-1); } else if (one.DecimalPart.Count != 0 && two.DecimalPart.Count == 0) { return(1); } else if (one.DecimalPart.Count == 0 && two.DecimalPart.Count == 0) { return(0); } else { for (int i = 0; i < minDecimalLength; i++) { if (one.DecimalPart[i] > two.DecimalPart[i]) { return(1); } else if (one.DecimalPart[i] < two.DecimalPart[i]) { return(-1); } } if (one.DecimalPart.Count > two.DecimalPart.Count) { return(1); } else if (one.DecimalPart.Count < two.DecimalPart.Count) { return(-1); } } return(0); } }