【问题标题】:C big number multiplicationC 大数乘法
【发布时间】:2021-12-08 09:29:15
【问题描述】:

我正在尝试为我的第一次测试编写一个大整数乘法,但如果 uint8_t 数字大于一个,则结果是错误的。我尝试了 2 天以找到解决方案并了解我做错了什么......

void main(void){
    uint8_t x[] = {0xFF};
    uint8_t y[] = {0xFF};
    uint8_t z[] = {0x00, 0x00};
    mul(x,1,y,1,z);
    printf("X*Y = Z: ");
    for(int i = 0; i < 2; i++)
        printf("%02X ",z[i]);
    printf("\n");
    //Output: X*Y = Z: FE 01 == FE01 CORRECT!

    uint8_t a[] = {0x0F, 0xFF};
    uint8_t b[] = {0x0F, 0xFF};
    uint8_t c[] = {0x00, 0x00, 0x00, 0x00};
    mul(a,2,b,2,c);

    printf("A*B = C: ");
    for(int i = 0; i < 4; i++)
        printf("%02X ",c[i]);
    printf("\n");
    //Output: A*B = C: 00 FE E0 01 != FFE001 WRONG?!

}
void mul(uint8_t *a, int a_n,uint8_t *b, int b_n,uint8_t *c){
    int i,j;
    uint16_t A;

    for(i = a_n-1; i >= 0; i--){
        A=0;
        for(j = b_n-1; j >= 0; j--){
            A += (uint16_t) a[i] * b[j]; 
            c[i+j+1] += A;
            A >>= 8;
        }
        c[i] = A;;
    }
}

【问题讨论】:

  • 你没有正确地进行携带。当c[i+j+1] + A 大于0xFF 时,需要将溢出进位到下一位。只有当a[i] * b[i] 溢出时,你才会携带。

标签: c multiplication biginteger bigint


【解决方案1】:

尝试使用此代码

#include <string.h>
 
int main()
{
    int a[100],b[100];
    int ans[200]={0};
    int i,j,tmp;
    char s1[101],s2[101];
    scanf(" %s",s1);
    scanf(" %s",s2);
    int l1 = strlen(s1);
    int l2 = strlen(s2);
    for(i = l1-1,j=0;i>=0;i--,j++)
    {
        a[j] = s1[i]-'0';
    }
    for(i = l2-1,j=0;i>=0;i--,j++)
    {
        b[j] = s2[i]-'0';
    }
    for(i = 0;i < l2;i++)
    {
        for(j = 0;j < l1;j++)
        {
            ans[i+j] += b[i]*a[j];
        }
    }
    for(i = 0;i < l1+l2;i++)
    {
        tmp = ans[i]/10;
        ans[i] = ans[i]%10;
        ans[i+1] = ans[i+1] + tmp;
    }
    for(i = l1+l2; i>= 0;i--)
    {
        if(ans[i] > 0)
            break;
    }
    printf("Product : ");
    for(;i >= 0;i--)
    {
        printf("%d",ans[i]);
    }
    return 0;
}```

【讨论】:

  • 虽然代码可以回答问题,但请发表解释。
【解决方案2】:

至少 1 个问题:

c[]中的溢出

c[i+j+1] += A; 可能会溢出c[]@Barmar

   // A += (uint16_t) a[i] * b[j]; 
   // c[i+j+1] += A;
   // A >>= 8;
   A = (uint16_t) a[i] * b[j] + A + c[i+j+1];
   c[i+j+1] = A & 0xFFu;  // or A % 256u
   A >>= 8;

固定代码示例(有其他小的改进)

// Using re-ordered parameters for better static code analysis
// Use const
// Idiomatic to use size_t for array sizing/indexing
// Perhaps return c[] to allow for chained calls.
uint8_t *mul(size_t a_n, const uint8_t a[a_n], size_t b_n, const uint8_t b[b_n],
    uint8_t c[a_n + b_n]) {

  for (size_t i = a_n; i-- > 0;) {
    unsigned A = 0; // Let compiler use the natural unsigned rather than force uint16_t
    for (size_t j = b_n; j-- > 0;) {
      A += 1u * a[i] * b[j] + c[i + j + 1]; // 1u * vs. cast, let compiler optimize
      c[i + j + 1] = A & 0xFFu;
      A >>= 8;
    }
    c[i] = A;
  }

  return c;
}

【讨论】:

  • 对于迂腐的:: 代码需要处理案例a_n == 0 &amp;&amp; b_n &gt; 0
猜你喜欢
  • 2015-06-09
  • 1970-01-01
  • 2019-05-20
  • 2021-07-05
  • 2015-02-18
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 2014-07-19
相关资源
最近更新 更多