原 大数运算

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

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

乘法:第一个乘数不动,循环第二个乘数的每一位,每一位先做循环加法,在根据位置对加的结果补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");

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java后端技术

22中编程语言的HelloWorld

721
来自专栏跟着阿笨一起玩NET

C#构造函数里的base和this的区别

父类的构造函数总是在子类之前执行的。既先初始化静态构造函数,后初始化子类构造函数。

1941
来自专栏angularejs学习篇

ref和out的区别在c#中 总结

520
来自专栏GreenLeaves

C#核编之内建数据类型

这个随笔中的重点之一是说明:C#中所提供的关键字都是相应系统类型的简化符号(如int是System.Int32类型的简化符号) 一、内建数据类型与层级结构 所有...

2346
来自专栏菩提树下的杨过

数据结构C#版笔记--顺序表(SeqList)

线性结构(Linear Stucture)是数据结构(Data Structure)中最基本的结构,其特征用图形表示如下: ? 即:每个元素前面有且只有一个元...

2089
来自专栏知识分享

学习C#(一)

赶紧好好学学自己的C#,,要不然要给做的东西说拜拜了,,,时间紧迫,,,真担心会食言..................... 在C#中以为只要类有构造方法,,...

3144
来自专栏林德熙的博客

C# 枚举转字符串 枚举转字符串字符串转枚举

如果把一个枚举转字符串,那么如何把字符串转枚举?可以使用 Enum.Parse 不过这个方法可以会抛异常,所以使用需要知道字符串是可以转

1991
来自专栏yl 成长笔记

c# 委托(Func、Action)

以前自己写委托都用 delegate, 最近看组里的大佬们都用 Func , 以及 Action 来实现, 代码简洁了不少, 但是看得我晕晕乎乎。 花点时间研究...

6673
来自专栏blackheart的专栏

[C#3] 2-var 类型推断

1.DEMO static void Main() { var Num = 6; var str = "乱舞春秋"; var dou =...

2036
来自专栏大内老A

由for V.S. for each想到的

一直想写一系列如何提高Performance和Scalability的文章,把我的相关经验和所知道的相关的技巧同大家分享。前一阵在园子里有一篇讨论for eac...

1888

扫码关注云+社区