使用字符串乘以非常大的数字

我正在尝试编写一个C程序,它执行两个数字的乘法而不直接使用乘法运算符,并且它应该考虑足够大的数字,以便即使通常添加这两个数字也不能通过直接相加来执行.

当我尝试(并且成功地)编写了一个使用字符串执行添加的C程序时,我的动机就是这样,我做了以下事情:

#include<stdio.h>
#define N 100000
#include<string.h>
void pushelts(char X[], int n){
int i, j;
for (j = 0; j < n; j++){
    for (i = strlen(X); i >= 0; i--){
        X[i + 1] = X[i];
    }
        X[0] = '0'; 
    }
}

int max(int a, int b){
    if (a > b){ return a; }
    return b;
}

void main(){
    char E[N], F[N]; int C[N]; int i, j, a, b, c, d = 0, e;
    printf("Enter the first number: ");
    gets_s(E);
    printf("\nEnter the second number: ");
    gets_s(F);
    a = strlen(E); b = strlen(F); c = max(a, b);
    pushelts(E, c - a); pushelts(F, c - b);
    for (i = c - 1; i >= 0; i--){
        e = d + E[i] + F[i] - 2*'0';
        C[i] = e % 10; d = e / 10;
    }
    printf("\nThe answer is: ");
    for (i = 0; i < c; i++){
        printf("%d", C[i]);
    }
    getchar();
}

它可以添加任意两个带“N”位的数字.现在,我将如何使用它来执行大数字的乘法运算?首先,我写了一个函数,它通过数字n(即0 <= n <= 9)执行数字的乘法,该数字将作为字符串输入.很容易看出这样的函数是如何写的;我叫它(*).现在主要目的是将两个数字(作为一个字符串输入)相乘.我们可能会看到第k个数字的数字(假设它是a1a2 ….. ak):

a1a2...ak = a1 x 10^(k - 1) + a2 x 10^(k - 2) + ... + ak-1 x 10 + ak

因此,使用为加法和函数(*)设计的解决方案可以实现两个数字的相乘.

如果第一个数字是x1x2 ….. xn而第二个数字是y1y2 …. yk,那么:

x1x2...xn x y1y2...yk = (x1x2...xn) x y1 x 10^(k-1) + .....

现在函数(*)可以将(x1x2 … xn)与y1相乘,乘以10 ^(k-1)只是在数字旁边加上k-1零;最后,我们将所有这些k项相互添加以获得结果.但困难在于只知道每个数字包含多少位数,以便每次在设计用于将它们添加到一起的循环内执行添加.我已经考虑过做一个空数组,并且每次都将(x1x2 …. xn)乘以yi x 10 ^(i-1)的结果加到它上面,但就像我说的那样我无法精确所需的边界,我不知道每次在每个获得的结果前面添加多少个零,以便使用上述算法将其添加到空数组.当我必须从char类型转换为int类型并且相反地进行多次转换时,会出现更多困难.也许我让它变得比它应该更复杂;我不知道是否有更简单的方法可以做到这一点,或者是否有我不知道的工具.我是编程的初学者,我不了解基本工具.

有没有人有解决方案或想法或算法呈现?谢谢.

最佳答案 我在SPOJ上做
Small Factorials问题时开发了一种算法.

该算法基于小学乘法.在上学日,我们通过将第一个数字的每个数字乘以第二个数字的最后一个数字来学习两个数字的乘法.然后将第一个数字的每个数字乘以第二个数字的倒数第二个数字,依此类推如下:

               1234
               x 56
         ------------
               7404
             +6170-   // - is denoting the left shift    
         ------------
              69104  

实际发生了什么:

  1. num1 = 1234, num2 = 56, left_shift = 0;
  2. char_array[] = all digits in num1
  3. result_array[]
  4. while(num2)
    • n = num2%10
    • num2 /= 10
    • carry = 0, i = left_shift, j = 0
    • while(char_array[j])
      i. partial_result = char_array[j]*n + carry
      ii. partial_result += result_array[i]
      iii. result_array[i++] = partial_result%10
      iv. carry = partial_result/10
    • left_shift++
  5. Print the result_array in reverse order.

您应该注意,如果num1和num2不超过其数据类型的范围,则上述算法有效.如果你想要更通用的程序,那么你必须读取char数组中的两个数字.逻辑将是相同的.将num1和num2声明为char数组.看实现:

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

int main(void)
{
    char num1[200], num2[200];
    char result_arr[400] = {'\0'};
    int left_shift = 0;

    fgets(num1, 200, stdin);
    fgets(num2, 200, stdin);

    size_t n1 = strlen(num1);
    size_t n2 = strlen(num2);   

    for(size_t i = n2-2; i >= 0; i--)
    {
        int carry = 0, k = left_shift;
        for(size_t j = n1-2; j >= 0; j--)
        {
            int partial_result = (num1[j] - '0')*(num2[i] - '0') + carry;
            if(result_arr[k])
                partial_result += result_arr[k] - '0';
            result_arr[k++] = partial_result%10 + '0';
            carry = partial_result/10;  
        }
        if(carry > 0)
            result_arr[k] = carry +'0'; 
        left_shift++;
    }
    //printf("%s\n", result_arr);

    size_t len = strlen(result_arr);
    for(size_t i = len-1; i >= 0; i-- )
        printf("%c", result_arr[i]);
    printf("\n");   
}

这不是标准算法,但我希望这会有所帮助.

点赞