【问题标题】:How to add or subtract very large numbers without bigint in C#?如何在 C# 中添加或减去没有 bigint 的非常大的数字?
【发布时间】:2013-09-27 14:43:47
【问题描述】:

首先让我说我是一个新手,对 C# 的知识知之甚少。

进入主题:我需要制作一个能够加/减非常大整数的程序。最初,使用 BigInt 只是为了发现它是不允许的。应该有一个合乎逻辑的解决方法吗?我有一个想法,它使用“小学方法”,您从右到左添加每个数字。

我创建了一个字符串,将其拆分为 char 数组并从右到左添加每个数字(GetUpperBound-i)。但这似乎不起作用。

我的代码:

string s, s2;
char[] c_arr, c_arr2;
int i, erg;

s = "1234";
s2 = "5678";
c_arr = s.ToCharArray();
c_arr2 = s2.ToCharArray();
for (i = 0; i <= c_arr.GetUpperBound(0); i++)
{
    erg = c_arr[c_arr.GetUpperBound(0)-i]+c_arr2[c_arr2.GetUpperBound(0)-i];
    Console.Write(erg);
}

Console.ReadKey();

【问题讨论】:

  • 但它似乎不起作用。你应该指定。
  • 各位数字之和超过9的情况你不需要处理吗?您需要将 1 带到下一列。
  • 将每个数组中的两个字符相加也不会达到您的预期。对于前两个,4 和 8,它将“4”转换为 52,将“8”转换为 56,因为这些是 char 表示。您需要将每个单独的字符转换为其整数值并对其进行求和。
  • Matt 好吧,我只是想先搞清楚基本结构。

标签: c# bigint


【解决方案1】:

下面的 SO 问题有一些有趣的方法。虽然答案在 Java 中,但您肯定会知道需要做什么。

How to handle very large numbers in Java without using java.math.BigInteger

【讨论】:

    【解决方案2】:

    您的“小学方法”代码存在一些问题。您没有考虑进位,您将 ascii 值而不是 0-9 之间的实际值相加,并且您以错误的顺序输出结果。

    下面的代码虽然不是很优雅,但确实产生了正确的结果:

    var s1 = "12345";
    var s2 = "5678";
    var carry = false;
    var result = String.Empty;
    
    if(s1.Length != s2.Length)
    {
        var diff = Math.Abs(s1.Length - s2.Length);
    
        if(s1.Length < s2.Length)
        {
            s1 = String.Join("", Enumerable.Repeat("0", diff)) + s1;
        }
        else
        {
            s2 = String.Join("", Enumerable.Repeat("0", diff)) + s2;
        }
    }
    
    
    for(int i = s1.Length-1;i >= 0; i--)
    {
        var augend = Convert.ToInt32(s1.Substring(i,1));
        var addend = Convert.ToInt32(s2.Substring(i,1));
        var sum = augend + addend;
        sum += (carry ? 1 : 0);
        carry = false;
        if(sum > 9)
        {
            carry = true;
            sum -= 10;
        }
    
        result = sum.ToString() + result;
    }
    
    if(carry)
    {
        result = "1" + result;
    }
    
    Console.WriteLine(result);
    

    【讨论】:

    • 谢谢。正是我想要的。我知道复制代码并不是很好。但我尽力去理解它,我也理解它。现在借助这段代码,我将尝试让所有算术运算符都能正常工作。
    • 我之所以来到这里,是因为我找到了another question,它作为这个副本被关闭了。但由于Substring 逻辑,如果两个字符串的长度不同,我认为这个答案不会起作用。
    • @Richardissimo 你是对的,如果字符串长度不匹配,它会失败。它很容易通过用前导零填充较短的值来修复。我已经编辑了答案以包含一些执行此操作的代码。
    • 另一种方法是迭代较长的字符串,并检查较短的字符串,如果超过末尾则返回零。
    【解决方案3】:

    下面的程序可以用来将两个大数相加,我使用了字符串生成器来存储结果。您可以添加最多包含“2,147,483,647”的数字。

    Using System;
    
    using System.Text;
    
    using System.Linq;
    
    public class Test
    
    {
    
    public static void Main()
    
    {
    
        string term1="15245142151235123512352362362352351236";
    
        string term2="1522135123612646436143613461344";
    
        StringBuilder sum=new StringBuilder();
    
        int n1=term1.Length;
    
        int n2=term2.Length;
    
        int carry=0;
    
        int n=(n1>n2)?n1:n2;
    
        if(n1>n2)
    
        term2=term2.PadLeft(n1,'0');
    
        else
    
        term1=term1.PadLeft(n2,'0');
    
        for(int i=n-1;i>=0;i--)
    
        {
    
            int value=(carry+term1[i]-48+term2[i]-48)%10;
    
            sum.Append(value);
    
            carry=(carry+term1[i]-48+term2[i]-48)/10;
    
        }
    
        char[] c=sum.ToString().ToCharArray();
    
        Array.Reverse(c);
    
        Console.WriteLine(c);
    
    }
    
    }
    

    【讨论】:

      【解决方案4】:
          public static int[] addTwoNumbers(string s1, string s2)
          {
      
              char[] num1 = s1.ToCharArray();
              char[] num2 = s2.ToCharArray();
              int sum = 0;
              int carry = 0;
              int size = (s1.Length > s2.Length) ? s1.Length + 1 : s2.Length + 1;
              int[] result = new int[size];
              int index = size - 1;
              int num1index = num1.Length - 1;
              int num2index = num2.Length - 1;
      
      
              while (true)
              {
                  if (num1index >= 0 && num2index >= 0)
                  {
                      sum = (num1[num1index]-'0') + (num2[num2index]-'0') + carry;
                  }
                  else if(num1index< 0 && num2index >= 0)
                  {
                      sum = (num2[num2index]-'0') + carry;
                  }
                  else if (num1index >= 0 && num2index < 0)
                  {
                      sum = (num1[num1index]-'0') + carry;
                  }
                  else { break; }
      
      
                  carry = sum /10;
                  result[index] = sum % 10;
                  index--;
                  num1index--;
                  num2index--;
              } 
      
                  if(carry>0)
                  {
                      result[index] = carry;
                  }
      
      
              return result;
          }
      

      【讨论】:

      • 感谢您的回答。你会考虑写一个简短的解释你的代码是如何回答这个问题的吗?
      【解决方案5】:
      string Add(string s1, string s2)
      {
          bool carry = false;
          string result = string.Empty;
          if(s1[0] != '-' && s2[0] != '-')
          {
              if (s1.Length < s2.Length)
                  s1 = s1.PadLeft(s2.Length, '0');
              if(s2.Length < s1.Length)
                  s2 = s2.PadLeft(s1.Length, '0');
      
              for(int i = s1.Length-1; i >= 0; i--)
              {
                  var augend = Convert.ToInt64(s1.Substring(i,1));
                  var addend = Convert.ToInt64(s2.Substring(i,1));
                  var sum = augend + addend;
                  sum += (carry ? 1 : 0);
                  carry = false;
                  if(sum > 9)
                  {
                      carry = true;
                      sum -= 10;
                  }
                  result = sum.ToString() + result;
              }
              if(carry)
              {
                  result = "1" + result;
              }
          }
      
          else if(s1[0] == '-' || s2[0] == '-')
          {
              long sum = 0;
              if(s2[0] == '-')
              {
                  //Removing negative sign
                  char[] MyChar = {'-'};
                  string NewString = s2.TrimStart(MyChar);
                  s2 = NewString;
      
                  if(s2.Length < s1.Length)
                      s2 = s2.PadLeft(s1.Length, '0');
      
                  for (int i = s1.Length - 1; i >= 0; i--)
                  {
                      var augend = Convert.ToInt64(s1.Substring(i,1));
                      var addend = Convert.ToInt64(s2.Substring(i,1));
                      if(augend >= addend)
                      {
                          sum = augend - addend;
                      }
                      else 
                      {
                          int temp = i - 1;
                          long numberNext = Convert.ToInt64(s1.Substring(temp,1));
                          //if number before is 0
                          while(numberNext == 0)
                          {
                              temp--;
                              numberNext = Convert.ToInt64(s1.Substring(temp,1));
                          }
                          //taking one from the neighbor number
                          int a = int.Parse(s1[temp].ToString());
                          a--;
                          StringBuilder tempString = new StringBuilder(s1);
                          string aString = a.ToString();
                          tempString[temp] = Convert.ToChar(aString);
                          s1 = tempString.ToString(); 
                          while(temp < i)
                          {
                              temp++;
                              StringBuilder copyS1 = new StringBuilder(s1);
                              string nine = "9"; 
                              tempString[temp] = Convert.ToChar(nine);
                              s1 = tempString.ToString();
                          }
                          augend += 10;
                          sum = augend - addend;
                      }
                      result = sum.ToString() + result;
                  }
                  //Removing the zero infront of the answer
                  char[] zeroChar = {'0'};
                  string tempResult = result.TrimStart(zeroChar);
                  result = tempResult;
              }
          }
      
          return result;
      }
      string Multiply(string s1, string s2)
      {
          string result = string.Empty;
          //For multipication
          bool Negative = false;
          if(s1[0] == '-' && s2[0] == '-')
              Negative = false;
          else if(s1[0] == '-' || s2[0] == '-')
              Negative = true;
      
          char[] minusChar = {'-'};
          string NewString;
          NewString = s2.TrimStart(minusChar);
          s2 = NewString;
          NewString = s1.TrimStart(minusChar);
          s1 = NewString;
      
          List<string> resultList = new List<string>();
          for(int i = s2.Length - 1; i >= 0; i--)
          {
              string multiplycation = string.Empty;
              for (int j = s1.Length - 1; j >= 0; j--)
              {
                  var augend = Convert.ToInt64(s1.Substring(j,1));
                  var addend = Convert.ToInt64(s2.Substring(i,1));
                  long multiply = augend * addend;
                  // print(multiply); 
                  multiplycation = multiply.ToString() + multiplycation;
              }
              //Adding zero at the end of the multiplication
              for (int k =  s2.Length - 1 - i; k > 0; k--)
              {
                  multiplycation += "0";
              }
              resultList.Add(multiplycation);
          }
      
          for (int i = 1; i < resultList.Count; i++)
          {
              resultList[0] = Add(resultList[0],resultList[i]);
          }
      
          //Finally assigning if negative negative sign in front of the number
          if(Negative)
              result = resultList[0].Insert(0,"-");
          else
              result = resultList[0];
      
          return result;
      }
      string Divide(string dividend, string divisor)
      {
          string result = string.Empty;
      
          int remainder = 0;
          int intNumberstoGet = divisor.Length;
          int currentInt = 0;
          int dividing = int.Parse(dividend.Substring(currentInt,intNumberstoGet));
      
          int intDivisor = int.Parse(divisor);
      
          while(currentInt < dividend.Length)
          {
              if(dividing == 0)
              {
                  currentInt++;
                  result += "0";
              }
              else
              {
                  while(dividing < intDivisor)
                  {
                      intNumberstoGet++;
                      dividing = int.Parse(dividend.Substring(currentInt,intNumberstoGet));
                  }
      
                  if (dividing > 0)
                  {   
                      remainder = dividing % intDivisor;
                      result += ((dividing - remainder) / intDivisor).ToString();
                      intNumberstoGet = 1;
      
                      if(currentInt < dividend.Length - 2)
                          currentInt += 2;
                      else
                          currentInt++;
      
                      if(currentInt != dividend.Length)
                      {
                          dividing = int.Parse(dividend.Substring(currentInt,intNumberstoGet));
                          remainder *= 10;
                          dividing += remainder;
                      }
                  }
              }
          }
          return result;
      }
      

      【讨论】:

      • 你可以通过在字符串前面加上“-”(负号)来减去。
      【解决方案6】:

      给你。另一个例子。它比公认的答案快 10 到 30 倍。

          static string AddNumStr(string v1, string v2)
          {
              var v1Len = v1.Length;
              var v2Len = v2.Length;
              var count = Math.Max(v1Len, v2Len);
              var answ = new char[count + 1];
              while (count >= 0) answ[count--] = (char)((v1Len > 0 ? v1[--v1Len] & 0xF:0) + (v2Len>0 ? v2[--v2Len]&0xF : 0));
              for (var i = answ.Length - 1; i >= 0; i--)
              {
                  if (answ[i] > 9)
                  {
                      answ[i - 1]++;
                      answ[i] -= (char)10;
                  }
                  answ[i] = (char)(answ[i] | 48);
              }
              return new string(answ).TrimStart('0');
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多