zoukankan      html  css  js  c++  java
  • 长数据类

    public class LongNumber
            {
                public enum NumberFlag
                {
                    /// <summary>
                    ///  负数
                    /// </summary>
                    Negative,
    
                    /// <summary>
                    /// 正数
                    /// </summary>
                    Positive
                }
    
                public NumberFlag Flag { get; set; }
                public string Number { get; set; }
    
                public LongNumber()
                {
                    this.Flag = NumberFlag.Positive;
                    this.Number = "0";
                }
    
                public LongNumber(string number)
                {
                    if (!LongNumber.CheckNumber(number))
                        throw new InvalidCastException("Input not is a number.");
    
                    this.Flag = NumberFlag.Positive;
                    this.Number = number;
                }
    
                public LongNumber(NumberFlag flag, string number)
                {
                    if (!LongNumber.CheckNumber(number))
                        throw new InvalidCastException("Input not is a number.");
    
                    this.Flag = flag;
                    this.Number = number;
                }
    
                public override string ToString()
                {
                    if (LongNumber.EqualsZero(this))
                        return "0";
                    else
                    {
                        return string.Format("{0}{1}", this.Flag == NumberFlag.Positive ? string.Empty : "-", this.Number.TrimStart('0'));
                    }
                }
    
                /// <summary>
                /// 检测给定字符串是否是一个有效的数字
                /// </summary>
                /// <param name="a"></param>
                /// <returns></returns>
                public static bool CheckNumber(string a)
                {
                    if (string.IsNullOrWhiteSpace(a))
                        return false;
    
                    var content = a;
                    foreach (var item in content)
                    {
                        if (!"0123456789.".Contains(item))
                        {
                            return false;
                        }
                    }
                    return true;
                }
    
                /// <summary>
                /// 检测给定的数字是否等于零
                /// </summary>
                /// <param name="a"></param>
                /// <returns></returns>
                public static bool EqualsZero(LongNumber a)
                {
                    var pos = a.Number.LastIndexOf('.');
                    var left = a.Number;
                    var right = string.Empty;
                    if (pos >= 0)
                    {
                        left = a.Number.Substring(0, pos);
                        right = a.Number.Substring(pos + 1);
                    }
    
                    if (left.Any(c => c != '0') || right.Any(c => c != '0'))
                        return false;
    
                    return true;
                }
    
                public static LongNumber Add(LongNumber a, LongNumber b)
                {
                    if (a.Flag == b.Flag)
                        return new LongNumber(a.Flag, AddWithoutFlag(a, b).Number);
                    else if (a.Flag == NumberFlag.Negative)
                        return LongNumber.MinusWithoutFlag(b, new LongNumber(NumberFlag.Positive, a.Number));
                    else
                        return LongNumber.MinusWithoutFlag(a, new LongNumber(NumberFlag.Positive, b.Number));
                }
    
                /// <summary>
                /// 计算a加b的结果
                /// </summary>
                /// <param name="a"></param>
                /// <param name="b"></param>
                /// <returns></returns>
                private static LongNumber AddWithoutFlag(LongNumber a, LongNumber b)
                {
                    //格式化数据
                    var inputA = a.Number;
                    var inputB = b.Number;
                    FormatNumber(ref inputA, ref inputB);
                    a.Number = inputA;
                    b.Number = inputB;
    
                    //定义进位值
                    var carry = 0;
                    var sbResult = new StringBuilder();
                    for (var i = a.Number.Length - 1; i >= 0; i--)
                    {
                        var tempA = a.Number[i];
                        var tempB = b.Number[i];
    
                        if (tempA == '.')
                        {
                            sbResult.Insert(0, tempA);
                            continue;
                        }
    
                        var tempResult = int.Parse(tempA.ToString()) + int.Parse(tempB.ToString()) + carry;
                        if (tempResult > 9)
                        {
                            carry = 1;
                            tempResult -= 10;
                        }
                        else
                        {
                            carry = 0;
                        }
                        sbResult.Insert(0, tempResult.ToString());
                    }
    
                    if (carry > 0)
                        sbResult.Insert(0, carry);
    
                    return new LongNumber(sbResult.ToString());
                }
    
                public static LongNumber Minus(LongNumber a, LongNumber b)
                {
                    if (a.Flag == b.Flag)
                    {
                        var c = LongNumber.MinusWithoutFlag(new LongNumber(a.Number), new LongNumber(b.Number));
                        if (a.Flag == NumberFlag.Negative)
                            c = new LongNumber(c.Flag == NumberFlag.Positive ? NumberFlag.Negative : NumberFlag.Positive, c.Number);
                        return c;
                    }
                    else
                    {
                        var c = LongNumber.AddWithoutFlag(new LongNumber(a.Number), new LongNumber(b.Number));
                        if (a.Flag == NumberFlag.Negative)
                            c = new LongNumber(c.Flag == NumberFlag.Positive ? NumberFlag.Negative : NumberFlag.Positive, c.Number);
                        return c;
                    }
                }
    
                /// <summary>
                /// 计算a减b的结果
                /// </summary>
                /// <param name="a"></param>
                /// <param name="b"></param>
                /// <returns></returns>
                private static LongNumber MinusWithoutFlag(LongNumber a, LongNumber b)
                {
                    var resultFlag = NumberFlag.Positive;
    
                    if (Compare(a, b) < 0)
                    {
                        resultFlag = NumberFlag.Negative;
                        var tempC = a.Number;
                        a.Number = b.Number;
                        b.Number = tempC;
                    }
    
                    //格式化数据
                    var inputA = a.Number;
                    var inputB = b.Number;
                    FormatNumber(ref inputA, ref inputB);
                    a.Number = inputA;
                    b.Number = inputB;
    
                    //定义借位
                    var borrow = 0;
                    var sbResult = new StringBuilder();
                    for (var i = a.Number.Length - 1; i >= 0; i--)
                    {
                        var tempA = a.Number[i];
                        var tempB = b.Number[i];
    
                        if (tempA == '.')
                        {
                            sbResult.Insert(0, tempA);
                            continue;
                        }
    
                        var tempResult = int.Parse(tempA.ToString()) - int.Parse(tempB.ToString()) - borrow;
                        if (tempResult < 0)
                        {
                            borrow = 1;
                            tempResult += 10;
                        }
                        else
                        {
                            borrow = 0;
                        }
                        sbResult.Insert(0, tempResult.ToString());
                    }
    
                    return new LongNumber(resultFlag, sbResult.ToString());
                }
    
                /// <summary>
                /// 计算a乘以b的结果
                /// </summary>
                /// <param name="a"></param>
                /// <param name="b"></param>
                /// <returns></returns>
                public static LongNumber Multiply(LongNumber a, LongNumber b)
                {
                    //获取小数位数
                    var aDecimalDigits = getDecimalDigits(a.Number);
                    var bDecimalDigits = getDecimalDigits(b.Number);
    
                    a.Number = a.Number.Replace(".", string.Empty);
                    b.Number = b.Number.Replace(".", string.Empty);
    
                    //用b从右到左的每一位去乘a
                    var totalResult = new LongNumber("0");
                    for (var i = b.Number.Length - 1; i >= 0; i--)
                    {
                        var tempResult = new LongNumber("0");
                        for (var j = 0; j < int.Parse(b.Number[i].ToString()); j++)
                        {
                            tempResult = Add(tempResult, a);
                        }
                        var sb = new StringBuilder();
                        for (var j = 0; j < b.Number.Length - 1 - i; j++)
                        {
                            sb.Append('0');
                        }
                        sb.Insert(0, tempResult.Number);
                        totalResult = Add(totalResult, new LongNumber(sb.ToString()));
                    }
    
                    var sbResult = new StringBuilder(totalResult.Number);
    
                    if (aDecimalDigits + bDecimalDigits > 0)
                        sbResult.Insert(sbResult.Length - aDecimalDigits - bDecimalDigits, '.');
    
                    var resultFlag = LongNumber.NumberFlag.Positive;
                    if (a.Flag != b.Flag)
                        resultFlag = NumberFlag.Negative;
    
                    return new LongNumber(resultFlag, sbResult.ToString());
                }
    
                /// <summary>
                /// 计算a除以b的结果,保留maxDecimalDigits位小数
                /// </summary>
                /// <param name="a"></param>
                /// <param name="b"></param>
                /// <param name="maxDecimalDigits"></param>
                /// <returns></returns>
                public static LongNumber Devide(LongNumber a, LongNumber b, int maxDecimalDigits = 2)
                {
                    var result = new StringBuilder();
                    var numberA = new StringBuilder();
    
                    //按照手动除法的规律去从高到低按位除
                    for (var i = 0; i < a.Number.Length; i++)
                    {
                        if (a.Number[i] == '.')
                        {
                            if (result.Length == 0)
                                result.Append(0);
                            result.Append('.');
                            continue;
                        }
    
                        //取被除数下一位
                        numberA.Append(a.Number[i].ToString());
                        var tempA = new LongNumber(numberA.ToString());
    
                        //如果当前取到的被除数位数与上次结果组合后大于等于除数,则可以除
                        if (Compare(tempA, b) >= 0)
                        {
                            var tempResult = 0;
                            //循环减一次除数,以累积计算当前位的最大商
                            while (Compare(tempA, b) >= 0)
                            {
                                tempResult++;
                                tempA = Minus(tempA, b);
                            }
                            result.Append(tempResult);
                            numberA.Clear();
                            numberA.Append(tempA);
                        }
                        //如果当前取到的被除数位数与上次结果组合后小于除数,则商当前位填0
                        else
                        {
                            result.Append(0);
                        }
                    }
    
                    var resultFlag = LongNumber.NumberFlag.Positive;
                    if (a.Flag != b.Flag)
                        resultFlag = NumberFlag.Negative;
    
                    return new LongNumber(resultFlag, result.ToString());
                }
    
                /// <summary>
                /// 计算a的b次方
                /// </summary>
                /// <param name="a"></param>
                /// <param name="b"></param>
                /// <returns></returns>
                public static LongNumber Power(LongNumber a, LongNumber b)
                {
                    var result = new LongNumber("1");
                    var counter = new LongNumber("0");
                    while (Compare(counter, b) < 0)
                    {
                        result = Multiply(result, new LongNumber(a.Flag, a.Number));
                        counter = Add(counter, new LongNumber("1"));
                    }
                    return result;
                }
    
                /// <summary>
                /// 比较两个长整数的大小
                /// </summary>
                /// <param name="a"></param>
                /// <param name="b"></param>
                /// <returns></returns>
                public static int Compare(LongNumber a, LongNumber b)
                {
                    if (LongNumber.EqualsZero(a) && LongNumber.EqualsZero(b))
                        return 0;
    
                    //格式化数据
                    var inputA = a.Number;
                    var inputB = b.Number;
                    FormatNumber(ref inputA, ref inputB);
                    a.Number = inputA;
                    b.Number = inputB;
    
                    var flagA = a.Flag;
                    var flagB = b.Flag;
    
                    if (!LongNumber.EqualsZero(a))
                        flagA = a.Flag;
    
                    if (!LongNumber.EqualsZero(b))
                        flagB = b.Flag;
    
                    if (flagA > flagB)
                        return 1;
                    else if (flagA < flagB)
                        return -1;
                    else
                    {
                        for (var i = 0; i < a.Number.Length; i++)
                        {
                            var itemA = int.Parse(a.Number[i].ToString());
                            var itemB = int.Parse(b.Number[i].ToString());
    
                            if (itemA == itemB)
                                continue;
    
                            if (itemA > itemB)
                                return 1;
                            else
                                return -1;
                        }
                        return 0;
                    }
                }
    
                /// <summary>
                /// 进制转换
                /// </summary>
                /// <param name="num">要转换的数字</param>
                /// <param name="toBase">要转换的进制基数</param>
                /// <returns>转换进制后每一位的数据</returns>
                public static List<LongNumber> BaseCast(LongNumber num, LongNumber toBase)
                {
                    if (LongNumber.Compare(toBase, new LongNumber("0")) < 0)
                        throw new InvalidCastException("toBase must be a positive number");
    
                    var result = new List<LongNumber>();
                    var temp = new LongNumber(num.Flag, num.Number);
                    while (true)
                    {
                        var a = LongNumber.Devide(temp, toBase, 0);
                        var b = LongNumber.Multiply(a, toBase);
                        var c = LongNumber.Minus(temp, b);
                        if (LongNumber.Compare(c, new LongNumber("0")) < 0)
                            c = LongNumber.Add(c, toBase);
                        result.Add(c);
    
                        if (LongNumber.EqualsZero(a))
                            break;
    
                        temp = a;
                    }
    
                    result.Reverse();
                    return result;
                }
    
                /// <summary>
                /// 往小数点后面的小数位末尾补0,在小数左边补零,以使两数左右对齐
                /// </summary>
                /// <param name="a"></param>
                /// <param name="b"></param>
                private static void FormatNumber(ref string a, ref string b)
                {
                    //获取小数位数
                    var aDecimalDigits = getDecimalDigits(a);
                    var bDecimalDigits = getDecimalDigits(b);
    
                    //补齐小数位数,使其右对齐
                    var sb = new StringBuilder();
                    for (var i = 0; i < Math.Abs(aDecimalDigits - bDecimalDigits); i++)
                    {
                        sb.Append('0');
                    }
                    if (aDecimalDigits > bDecimalDigits)
                    {
                        sb.Insert(0, b);
                        b = sb.ToString();
                    }
                    else if (bDecimalDigits > aDecimalDigits)
                    {
                        sb.Insert(0, a);
                        a = sb.ToString();
                    }
    
                    //补齐左边位数,使其可以左对齐
                    sb.Clear();
                    for (var i = 0; i < Math.Abs(a.Length - b.Length); i++)
                    {
                        sb.Append('0');
                    }
    
                    if (a.Length > b.Length)
                    {
                        sb.Append(b);
                        b = sb.ToString();
                    }
                    else if (b.Length > a.Length)
                    {
                        sb.Append(a);
                        a = sb.ToString();
                    }
                }
    
                /// <summary>
                /// 获取小数位数
                /// </summary>
                /// <param name="a"></param>
                /// <returns></returns>
                private static int getDecimalDigits(string a)
                {
                    return a.IndexOf('.') >= 0 ? a.Length - a.IndexOf('.') - 1 : 0;
                }
            }
  • 相关阅读:
    第一章计算机系统知识
    Java面试宝典摘抄
    Java的容器类Collection和Map
    log4j.properties 详解与配置步骤(转)
    JSTL中的TLD配置和使用。
    (原创)mybatis学习四,利用mybatis自动创建代码
    C#常用方法
    Spring 3.x jar 包详解 与 依赖关系
    spring mvc JSON实现方式
    Structs2配置文件相关说明
  • 原文地址:https://www.cnblogs.com/nanfei/p/10268391.html
Copyright © 2011-2022 走看看