【问题标题】:Adding two numbers [1, 10^10000] as arrays of chars - C添加两个数字 [1, 10^10000] 作为字符数组 - C
【发布时间】:2017-06-19 12:12:07
【问题描述】:

我解决了这个问题,首先计算出两个给定数字的长度,然后将具有较少数字(如果存在的话)的数字对齐到一个新数组中,这样一、十、百等与较大数字的对齐,数十、数百等 然后我想将每两个对齐元素的总和(mod 为 10)保存到一个新数组中,同时检查数字总和是否大于 10 - 只是基本的总和。现在问题出现在将两个元素添加到 aplusb 整数中,我尝试通过编写来修复它

int aplusb = (lengthA[max-i]-'0') +(temp[max-i]-'0');

但它不起作用。我被困住了,我不知道该怎么办。请帮忙。

整个代码:

#include <stdio.h>
#include <math.h>

int main(){
    char a[10000];
    char b[10000];
    scanf("%s %s", &a, &b);
    char sum[10000];
    int lengthA = 0;
    int lengthB = 0;

    int i = 0;
    while(a[i]){
        i++;
    } lengthA = i;

    i = 0;
    while(b[i]){
        i++;
    } lengthB = i;
    char temp[10000];

    int aplusb;
    int carry = 0;

    int max = lengthA;
    int difference = abs(lengthA - lengthB); 
    if(lengthA>lengthB){
        for(i=0; i<lengthA; i++){
            temp[i+difference]=b[i];
        }
        for(i=0; i<=max; i++){
            aplusb = lengthA[max-i]+temp[max-i]; //<-- this is the problematic line
            if(carry = 1) aplusb++;
            if(aplusb>9){
                carry = 1;
                aplusb%=10;
            }
            sum[i]=aplusb;
        }
    }

    for(i=0; i<=max; i++){
        printf("%c", sum[i]);
    }

    /*
    if(lengthB>lengthA){
        max = lengthB;
        for(i=0; i<lengthB; i++){
            temp[i+difference]=a[i];
        }
    }*/

    return 0;
}

【问题讨论】:

  • 10 ^ 1000010010int 就足够了。
  • if(carry = 1) 是分配。改为if(carry == 1)
  • 我的意思是 10 的 10000 次方 @Olaf
  • 为什么这么复杂?为什么要使用具有实现定义签名的类型?
  • 我想不出一个更简单的方法来总结巨大的数字。 - 还有第二个问题是什么意思,我不太明白。 @Olaf

标签: c arrays char numbers sum


【解决方案1】:

对非常大的数进行运算和存储非常类似于进行运算和存储多项式,即 x = 10. a0 + a1.10 + a2.10^2 ... + an.10^n。

互联网上有很多多项式库,您可以从中找到灵感。对非常大的数字的所有操作都可以用多项式表示。这意味着通过使用基数 2^8,甚至基数 2^63,而不是基数 10 在内部存储大量数字,您将大大提高性能。

您还必须在操作后对系数进行归一化以使其保持正数。运算可能会导致负系数,这很容易修复,因为它与减法后的借位非常相似,这意味着系数必须比您的基数大 1bit。

要转换回以 10 为底,您需要将 r(您的结果)求解为 v(您的值),例如 r(10)=v(2^63)。如果您强制执行正系数规则,这只有一种解决方案。

[note] 再想一想:毕竟正系数的规则可能只是打印所必需的。

示例:添加。 没有内存错误检查

int addPolys(signed char** result, int na, const signed char* a, int nb, const signed char* b)
{
  int i, nr, nmin, carry, *r;

  nr = max(na, nb) + 1;
  nmin = min(na, nb);

  r = malloc(sizeof(signed char) * (na + nb + 1));

  if (nb < na)
  {
    nr = nb;
  }

  for (i = 0; i < nmin; ++i)
  {
    r[i] = a[i] + b[i];
  }
  for (; i < na; ++i)
  {
    r[i] = a[i];
  }
  for (; i < nb; ++i)
  {
    r[i] = b[i];
  }
  r[nr - 1] = 0;
  // carry - should really be a proc of its own, unoptimized
  carry = 0;
  for (i = 0; i < nr; ++i)
  {
    r[i] += carry;
    if (r[i] > 10)
    {
       carry = r[i] / 10;
       r[i] %= 10;
    }
    else if (r[i] < 0)
    {
       carry = (r[i] / 10) - 1;
       r[i] -= (carry * 10);
    }
    else
      carry = 0;
  }

  // 'remove' leading zeroes 
  for (i = nr - 1; i > 0; --i)
  {
    if (r[i] != 0) break;
  } 
  ++i;

  *result = r;
  if (i != nr)
  {      
    *result = realloc(i * sizeof(signed char));  
  }
  return i;  // return number of digits (0 being 1 digit long)
 }

【讨论】:

  • 感谢您的广泛回答,但我将首先尝试通过实现整数数组来求和。我想到了 +1 位:)。
  • 是的,使用 base 10 可能更简单。数学是一样的。
  • 很久以前我写了一个多项式库。不幸的是,它在 c++ 中,但它定义了所有基本函数,例如多项式加法、乘法和除法。 mroy.chez-alice.fr/polynomials/index.html
【解决方案2】:

该代码现在适用于任何两个最多一万位的正数:

#include <stdio.h>
#include <math.h>
#include <string.h>

int main(){
    char chara[10000];
    char charb[10000];
    scanf("%s %s", &chara, &charb);
    int lengthA = strlen(chara);
    int lengthB = strlen(charb);
    int max = lengthA;
    if(lengthB>lengthA) max=lengthB;
    int dif = abs(lengthA - lengthB);

    //ustvari int tabele
    int a[max];
    int b[max];
    int sum[max+1];

    // nastavi nule
    int i;
    for(i=0; i<max; i++){
        a[i] = 0;
        b[i] = 0;
        sum[i] = 0;
    } sum[max] = 0;

    //prekopiraj stevila iz char v int tabele &obrni vrstni red

    for(i=0; i<lengthA; i++){
        a[i] = chara[lengthA-i-1]-'0';
    }
    for(i=0; i<lengthB; i++){
        b[i] = charb[lengthB-i-1]-'0';
    }

    int vsota;
    int prenos = 0;

    for(i=0; i<max; i++){
        vsota = a[i]+b[i] + prenos;
        if(vsota>=10) prenos = 1;
        else if (vsota<10) prenos = 0;
        sum[i]=vsota%10;
    }

    if(prenos==1){
        sum[max] = 1;
        for(i = max; i>=0; i--){
            printf("%d", sum[i]);
        }
    } else {
        for(i = max-1; i>=0; i--){
            printf("%d", sum[i]);
        }
    }
    return 0;
}

【讨论】:

  • 详细信息:“现在为任何两个最多一万位的正数工作”-->减一。 chara[10000]; 足以存储 9999 位 字符串null 字符需要 1。
  • 简化:考虑if(vsota&gt;=10) prenos = 1; else if (vsota&lt;10) prenos = 0; sum[i]=vsota%10;,而不是sum[i]=vsota%10; prenos = vsota/10;
猜你喜欢
  • 2019-03-31
  • 2020-02-09
  • 1970-01-01
  • 2020-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-21
  • 1970-01-01
相关资源
最近更新 更多