首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >原 大数运算

原 大数运算

作者头像
魂祭心
发布2018-05-17 16:10:13
6290
发布2018-05-17 16:10:13
举报
文章被收录于专栏:魂祭心魂祭心

加法: 逐位相加,要考虑到进位的情况。

减法:逐位相减,要考虑到借位的情况。

乘法:第一个乘数不动,循环第二个乘数的每一位,每一位先做循环加法,在根据位置对加的结果补0,最后把结果累加起来。

除法:循环从被除数中减去除数,减去多少次结果就是多少,直接写运行很慢,做了一点优化,看操作数之间长度差是否大于1,如果大于1,则本次除数后补差距-1个0,循环可以控制在百次左右。

 public class BigDataOperator
    {
        /// <summary>
        /// 加法
        /// </summary>
        /// <param name="lOperand"></param>
        /// <param name="rOperand"></param>
        /// <returns></returns>
        public static string Add(string lOperand, string rOperand)
        {
            if (string.IsNullOrEmpty(lOperand) || string.IsNullOrEmpty(rOperand)) throw new ArgumentException("not a number");
            bool isNeginative = false;
            if (IsNegative(lOperand) && IsNegative(rOperand))
            {
                isNeginative = true;
                lOperand = lOperand.Trim('-');
                rOperand = rOperand.Trim('-');
            }
            if (IsNegative(lOperand) && !IsNegative(rOperand)) return Minus(rOperand, lOperand.Trim('-'));
            if (!IsNegative(lOperand) && IsNegative(rOperand)) return Minus(lOperand, rOperand.Trim('-'));


            string shortNumStr = lOperand;
            string longNumStr = rOperand;
            if (lOperand.Length > rOperand.Length)
            {
                shortNumStr = rOperand;
                longNumStr = lOperand;
            }
            StringBuilder result = new StringBuilder();

            //长数加短数 逐位相加
            var difference = longNumStr.Length - shortNumStr.Length;  //长度差
            int carry = 0;//进位
            for (int i = longNumStr.Length - 1; i >= 0; i--)
            {
                var shortIndex = i - difference;
                var lNum = longNumStr[i] - (int)'0';
                int sNum = 0;
                if (shortIndex >= 0)
                {
                    sNum = shortNumStr[shortIndex] - (int)'0';
                }
                var sum = lNum + sNum + carry;
                if (sum > 9)
                {
                    carry = 1;
                    result.Insert(0, sum - 10);
                }
                else
                {
                    carry = 0;
                    result.Insert(0, sum);
                }
            }
            //最后可能结果增长了一位
            if (carry != 0) result.Insert(0, 1);
            return (isNeginative ? "-" : "") + result.ToString().TrimStart('0');
        }
        /// <summary>
        /// 减法
        /// </summary>
        /// <param name="lOperand"></param>
        /// <param name="rOperand"></param>
        /// <returns></returns>
        public static string Minus(string lOperand, string rOperand)
        {
            if (string.IsNullOrEmpty(lOperand) || string.IsNullOrEmpty(rOperand)) throw new ArgumentException("not a number");
            bool isNeginative = true;
            if (IsNegative(lOperand) && IsNegative(rOperand)) return Minus(rOperand.TrimStart('-'), lOperand.TrimStart('-'));
            if (IsNegative(lOperand) && !IsNegative(rOperand)) return Add(lOperand, "-" + rOperand);
            if (!IsNegative(lOperand) && IsNegative(rOperand)) return Add(lOperand, rOperand.Trim('-'));

            var bigNum = rOperand;
            var smallNum = lOperand;
            if (IsBigger(lOperand, rOperand))
            {
                isNeginative = false;
                bigNum = lOperand;
                smallNum = rOperand;
            }
            if (lOperand == rOperand) return "0";
            StringBuilder result = new StringBuilder();
            //逐位相加
            var difference = bigNum.Length - smallNum.Length; //长度差
            int borrowNum = 0;  //借位
            for (int i = bigNum.Length - 1; i >= 0; i--)
            {
                var shortIndex = i - difference;
                var lNum = bigNum[i] - (int)'0' - borrowNum;
                int sNum = 0;
                if (shortIndex >= 0)
                {
                    sNum = smallNum[shortIndex] - (int)'0';
                }

                if (lNum < sNum)
                {
                    borrowNum = 1;
                }
                else
                {
                    borrowNum = 0;
                }
                var diff = lNum + borrowNum * 10 - sNum;
                result.Insert(0, diff);
            }
            return (isNeginative ? "-" : "") + result.ToString().TrimStart('0');
        }
        /// <summary>
        /// 乘法
        /// </summary>
        /// <param name="lOperand"></param>
        /// <param name="rOperand"></param>
        /// <returns></returns>
        public static string Multiple(string lOperand, string rOperand)
        {
            if (string.IsNullOrEmpty(lOperand) || string.IsNullOrEmpty(rOperand)) throw new ArgumentException("not a number");
            bool isNeginative = true;
            if (!IsNegative(lOperand) && !IsNegative(rOperand)) isNeginative = false;
            if (IsNegative(lOperand) && IsNegative(rOperand)) isNeginative = false;

            lOperand = lOperand.Trim('-');
            rOperand = rOperand.Trim('-');

            StringBuilder result = new StringBuilder();
            //逐位相加
            var resultTemp = "0";
            for (int i = rOperand.Length - 1; i >= 0; i--)
            {
                var num = rOperand[i] - (int)'0';
                var bitemp = "0";
                for (int j = 0; j < num; j++)    //重复加
                {
                    bitemp = Add(bitemp, lOperand);
                }
                for (int k = 0; k < rOperand.Length - 1 - i; k++) //尾部补0
                {
                    bitemp = bitemp + "0";
                }
                resultTemp = Add(resultTemp, bitemp);
            }
            return (isNeginative ? "-" : "") + resultTemp.TrimStart('0');
        }
        /// <summary>
        /// 除法(小数舍去)
        /// </summary>
        /// <param name="lOperand"></param>
        /// <param name="rOperand"></param>
        /// <returns></returns>
        public static string Divided(string lOperand, string rOperand)
        {
            if (string.IsNullOrEmpty(lOperand) || string.IsNullOrEmpty(rOperand)) throw new ArgumentException("not a number");
            bool isNeginative = true;
            if (!IsNegative(lOperand) && !IsNegative(rOperand)) isNeginative = false;
            if (IsNegative(lOperand) && IsNegative(rOperand)) isNeginative = false;

            lOperand = lOperand.Trim('-');
            rOperand = rOperand.Trim('-');
            if (lOperand == rOperand) return (isNeginative ? "-" : "") + '1';
            if (!IsBigger(lOperand, rOperand)) return "0";
            string result = "0";
            var temp = lOperand;
            while (true)   //循环减法
            {
                var dividedNum = rOperand;
                var times = "1";
                var differ = temp.Length - rOperand.Length;//优化
                if (differ > 1)
                {
                    for (int i = 0; i < differ - 1; i++)
                    {
                        dividedNum = dividedNum + "0";
                        times = times + "0";
                    }
                }

                temp = Minus(temp, dividedNum);
                if (IsNegative(temp))
                {
                    break;
                }
                result = Add(result, times);
            }

            return (isNeginative ? "-" : "") + result.TrimStart('0');
        }
        /// <summary>
        /// 判断是否大于
        /// </summary>
        /// <param name="lOperand"></param>
        /// <param name="rOperand"></param>
        /// <returns></returns>
        public static bool IsBigger(string lOperand, string rOperand)
        {
            if (string.IsNullOrEmpty(lOperand) || string.IsNullOrEmpty(rOperand)) throw new ArgumentException("not a number");
            bool isAllNagative = false;
            if (IsNegative(lOperand) && !IsNegative(rOperand)) return false;
            if (!IsNegative(lOperand) && IsNegative(rOperand)) return true;
            if (IsNegative(lOperand) && IsNegative(rOperand))
            {
                isAllNagative = true;
            }
            string shortNumStr = lOperand;
            string longNumStr = rOperand;
            if (lOperand.Length > rOperand.Length)
            {
                return isAllNagative ? false : true;
            }
            if (lOperand.Length < rOperand.Length)
            {
                return isAllNagative ? true : false;
            }

            for (int i = 0; i < lOperand.Length; i++)
            {
                if (lOperand[i] > rOperand[0])
                {
                    return isAllNagative ? false : true;
                }
                else if (lOperand[i] < rOperand[0])
                {
                    return isAllNagative ? true : false;
                }
                else
                {
                    continue;
                }
            }
            //equal
            return false;
        }
        /// <summary>
        /// 判断是不是负数
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool IsNegative(string value)
        {
            if (string.IsNullOrEmpty(value)) throw new ArgumentException("not a number");
            return value.ElementAt(0) == '-';
        }
    }

测试:

            Assert.AreEqual(BigDataOperator.IsNegative("4444444444444444444444444444444444444"), false);
            Assert.AreEqual(BigDataOperator.IsNegative("-14444444444444444444444444444444444444"), true);


            Assert.AreEqual(BigDataOperator.IsBigger("5555555555555", "5555555555555"), false);
            Assert.AreEqual(BigDataOperator.IsBigger("5555555555555", "-5555555555555"), true);
            Assert.AreEqual(BigDataOperator.IsBigger("-5555555555555", "5555555555555"), false);
            Assert.AreEqual(BigDataOperator.IsBigger("66666666666666", "555555555555"), true);
            Assert.AreEqual(BigDataOperator.IsBigger("555555555555", "66666666666666"), false);

            //add
            Assert.AreEqual(BigDataOperator.Add("555555555555", "66666666666666"), "67222222222221");
            Assert.AreEqual(BigDataOperator.Add("555555555555", "-66666666666666"), "-66111111111111");
            Assert.AreEqual(BigDataOperator.Add("-555555555555", "66666666666666"), "66111111111111");
            Assert.AreEqual(BigDataOperator.Add("-555555555555", "-66666666666666"), "-67222222222221");
            //minus
            Assert.AreEqual(BigDataOperator.Minus("555555555555", "66666666666666"), "-66111111111111");
            Assert.AreEqual(BigDataOperator.Minus("555555555555", "-66666666666666"), "67222222222221");
            Assert.AreEqual(BigDataOperator.Minus("-555555555555", "66666666666666"), "-67222222222221");
            Assert.AreEqual(BigDataOperator.Minus("-555555555555", "-66666666666666"), "66111111111111");
            //multy
            Assert.AreEqual(BigDataOperator.Multiple("4236586974332423432", "13216545765875841324"), "55993045637377932557226829234811503968");
            Assert.AreEqual(BigDataOperator.Multiple("4236586974332423432", "-13216545765875841324"), "-55993045637377932557226829234811503968");
            Assert.AreEqual(BigDataOperator.Multiple("-4236586974332423432", "13216545765875841324"), "-55993045637377932557226829234811503968");
            Assert.AreEqual(BigDataOperator.Multiple("-4236586974332423432", "-13216545765875841324"), "55993045637377932557226829234811503968");
            //divide
            Assert.AreEqual(BigDataOperator.Divided("32464576587684354324325632454325", "666623666466626666"), "48700006046529");
            Assert.AreEqual(BigDataOperator.Divided("-32464576587684354324325632454325", "666623666466626666"), "-48700006046529");
            Assert.AreEqual(BigDataOperator.Divided("32464576587684354324325632454325", "-666623666466626666"), "-48700006046529");
            Assert.AreEqual(BigDataOperator.Divided("-32464576587684354324325632454325", "-666623666466626666"), "48700006046529");
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档