两个长度为40的大数相乘

huangapple go评论64阅读模式
英文:

Multiplication of two large numbers of strlen 40 each

问题

以下是您提供的C代码的翻译,我已将代码部分排除,只返回注释和字符串。如果需要更多帮助,请随时告诉我。

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

#define MAX_LEN 200

int checkValidInputNum(char*);

int main() {
    
    char first_num[MAX_LEN];
    char second_num[MAX_LEN];
    printf("请输入第一个数字:\n");
    scanf("%s", first_num);
    
    checkValidInputNum(first_num);
    
    printf("请输入第二个数字:\n");
    scanf("%s", second_num);
    checkValidInputNum(second_num);
    
    int output_num_len = strlen(first_num) + strlen(second_num);

    int shifting, inputDataRemainder, inputDataQuotient;

    int output_num[output_num_len];
    for (int i = 0; i < output_num_len; i++)
    {
        output_num[i] = 0; // 用零填充output_num_len长度的输出字符串
    }
    
    for(int i = 0; i < strlen(first_num) ; i++)
    {
        for (int j = 0 ; j < strlen(second_num); j++)
        {
            shifting = (strlen(first_num) - 1 - i) + (strlen(second_num) - 1 - j);
            inputDataRemainder = ((first_num[i] - 48) * (second_num[j] - 48)) % 10;
            inputDataQuotient = floor((first_num[i] - 48) * (second_num[j] - 48) / 10);

            if (output_num[0 + shifting] + inputDataRemainder > 9)
            {
                output_num[1 + shifting] += floor((inputDataRemainder + output_num[0 + shifting]) / 10);
                output_num[0 + shifting] = (output_num[0 + shifting] + inputDataRemainder) % 10;
            }
            else
            {
                output_num[0 + shifting] += inputDataRemainder;
            }
            
            if (output_num[1 + shifting] + inputDataQuotient > 9)
            {
                output_num[2 + shifting] += floor((inputDataQuotient + output_num[1 + shifting]) / 10);
                output_num[1 + shifting] = (output_num[1 + shifting] + inputDataQuotient) % 10;
            }
            else
            {
                output_num[1 + shifting] += inputDataQuotient;
            }
        }
    }

    if (output_num[output_num_len - 1] != 0) printf("%i", output_num[output_num_len - 1]);
    
    printf("答案是:");
    for (int i = output_num_len - 2; i > -1  ; i--)
    {
        printf("%i", output_num[i]);
    }
    printf("\n");
}

int checkValidInputNum(char* text)
{
    for(int i = 0 ; i < strlen(text) ; i++)
    {
        if (text[i] < 48 || text[i] > 57)
        {
            printf("请重新输入您的输入:\n");
            scanf("%s", text);
            return checkValidInputNum(text);
        }
    }
    return 0;
}

这段代码是用C编写的,目的是计算两个大数的乘积。它接受两个小于200位的数字作为输入,并输出一个整数。代码中包含了一些输入验证和数字乘法的逻辑。根据您提供的输入示例和期望输出,您认为有问题的部分可能与output_num缓冲区的偏移计算相关。您还问到inputDataRemainderinputDataQuotient是否正确,这些变量在处理乘法的余数和商时似乎是正确的。

您提供的输出与期望输出不一致,这可能是由于某些逻辑错误导致的。我建议您仔细检查代码的乘法逻辑,特别是与shiftinginputDataRemainderinputDataQuotient相关的部分,以确保它们按预期工作。您还可以使用调试工具来跟踪代码的执行过程,以查找潜在的错误。

英文:
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;math.h&gt;
#define MAX_LEN 200
int checkValidInputNum(char*);
int main() {
char first_num[MAX_LEN];
char second_num[MAX_LEN];
printf(&quot;Please Enter your first number:\n&quot;);
scanf(&quot;%s&quot;, first_num);
checkValidInputNum(first_num);
printf(&quot;Please Enter your second number:\n&quot;);
scanf(&quot;%s&quot;, second_num);
checkValidInputNum(second_num);
int output_num_len = strlen(first_num) +strlen(second_num);
int shifting, inputDataRemainder, inputDataQuotient;
int output_num[output_num_len];
for (int i = 0; i &lt; output_num_len; i++)
{
output_num[i]=0; //Fill output string of output_num_len with zeroes
//printf(&quot;%i&quot;, output[i]);
}
for(int i = 0 ; i &lt;strlen(first_num) ; i++)
{
for (int j= 0 ; j &lt; strlen(second_num); j++)
{
shifting = (strlen(first_num) -1 - i) +(strlen(second_num) -1 - j);
inputDataRemainder = ((first_num[i]-48) * (second_num[j]-48)) % 10;
inputDataQuotient = floor((first_num[i]-48) * (second_num[j]-48)/10);
if (output_num[0+shifting] + inputDataRemainder &gt; 9)
{
output_num[1+shifting] += floor((inputDataRemainder + output_num[0+shifting]) / 10);
output_num[0+shifting] = (output_num[0+shifting] + inputDataRemainder)%10;
//printf(&quot;Check1&quot;);
}
else
{
output_num[0+shifting] += inputDataRemainder;
//printf(&quot;Check2&quot;);
}
if (output_num[1+shifting] + inputDataQuotient &gt; 9)
{
output_num[2+shifting] += floor((inputDataQuotient + output_num[1+shifting]) / 10);
output_num[1+shifting] = (output_num[1+shifting] + inputDataQuotient)%10;
//printf(&quot;Check3&quot;);
}
else
{
output_num[1+shifting] += inputDataQuotient;
//printf(&quot;Check4&quot;);
}
}
}
if (output_num[output_num_len-1] != 0) printf(&quot;%i&quot;, output_num[output_num_len - 1]);
printf(&quot;The answer is:&quot;);
for (int i = output_num_len - 2; i &gt; -1  ; i--)
{
printf(&quot;%i&quot;, output_num[i]);
}
printf(&quot;\n&quot;);
}
int checkValidInputNum(char* text)
{
for(int i = 0 ; i &lt;strlen(text) ; i++)
{
if (text[i] &lt; 48 || text[i] &gt; 57)
{
printf(&quot;Please Enter your input again:\n&quot;);
scanf(&quot;%s&quot;, text);
return checkValidInputNum(text);
}
}
return 0;
}

I am trying to multiple two large numbers to determine the output. Each number is smaller than 200-digits in length. The output should be a single integer.

Input params:
first_num: 2312730179961343894238242938502761288775
second_num: 8783549656928600320634308588114585640082

Expected output: 20313980378767882242186765287491308230145683219100946334095285964698734616679550
Observed output:
110313971037876788224218676528749130822101456832190100946334095285964698734616679550

I am assuming that my calculation is wrong with output_num buffer string shifting. Could anyone please confirm and help? Is my inputDataRemainder and Quotient are ok?

答案1

得分: 5

你在这一行之后没有检查output_num[2+shifting]是否超过9:

output_num[2+shifting] += floor((inputDataQuotient + output_num[1+shifting]) / 10);

一个更简单的例子是,输入9909 101会得到输出9100809,而正确答案是1000809

这是因为最高位的值是9,而第二高位的值是10,所以它们被连接在一起并打印为910

要解决这个问题,你应该检查每一位是否超过9,如果是的话,就要处理进位。

可以这样做:

for (int i = 0; i < output_num_len - 1; i++)
{
    if (output_num[i] > 9)
    {
        output_num[i] %= 10;
        output_num[i + 1]++;
    }
}

另外,请注意这一行:

if (output_num[output_num_len-1] != 0) printf(" %i", output_num[output_num_len - 1]);

位置不正确,所以最高位可能会在消息"The answer is:"之前被打印出来。

英文:

You are not checking if output_num[2+shifting] exceeds 9 after this line:

output_num[2+shifting] += floor((inputDataQuotient + output_num[1+shifting]) / 10);

As a simpler example, an input 9909 101 results in an output 9100809 while the correct answer is 1000809.

This is because the top digit has the value 9 and the second top digit has the value 10, so they are concatenated and printed as 910.

To resolve this issue, you shold check if each digits exceeds 9 and deal with carry if yes.

This can be done like this:

for (int i = 0; i &lt; output_num_len - 1; i++)
{
if (output_num[i] &gt; 9)
{
output_num[i] %= 10;
output_num[i + 1]++;
}
}

Also note that the line

if (output_num[output_num_len-1] != 0) printf(&quot;%i&quot;, output_num[output_num_len - 1]);

has a wrong position, so the top digit may be printed before the message "The answer is:".

答案2

得分: 2

总结一下,你的代码通过将每一对数字相乘,然后将它们全部相加并进行移位,从而得到最终的答案。

例如,12 x 45 的计算是通过将 1x4(移位2),1x5(移位1),2x4(移位1)和2x5(移位0)相乘来实现的。

问题似乎在于,当你将移位后的数字相加到答案中时,你没有让进位发生在答案的多个数字位上。例如,假设 inputDataRemainder 连续20次为8,而 shifting 相同(假设为30),然后看看 output_num[32]、[31] 和 [30]。第一次,你将8加到 output_num[30],所以这三个数字分别为0、0、8。然后你检测到再添加另一个8会使它大于9,因此你应该进位到 output_num[31],现在你有0、1、6。这是正确的。但你没有从 output_num[31] 进位到 output_num[32],所以在添加了一堆8之后,你得到的是0、10、4,而不是1、0、4。

在你的测试中,你期望得到一个以20313开头的输出,但实际上你得到的是110313。这是因为它不是1、1、0、3、1、3,而实际上是1、10、3、1、3。这个10没有像应该的那样进位到输出的第一位数字。

你可以通过将进位操作放入一个循环中来修复这个问题,这样它将进行多次进位,直到不再需要为止。你不需要分别处理 inputDataRemainder 和 inputDataQuotient - 你可以将它们都视为余数,然后执行进位循环。

或者你可以让数字变得太大,然后在最后修复它。你可以在相加移位后的数字时忽略进位,然后在打印数字之前(或在打印时)检查数字是否大于9,然后取商和余数,将商加到下一个数字上,如果那个数字大于9,那么再次执行相同的操作,依此类推。

英文:

To summarize, your code works by multiplying each pair of digits and adding them all up with shifting to get a final answer.

E.g. 12 x 45 works by multiplying 1x4 (shift 2), 1x5 (shift 1), 2x4 (shift 1) and 2x5 (shift 0).

The bug seems to be that when you add the shifted numbers into the answer you don't make carries happen more than one digit in the answer. For example, let's say that inputDataRemainder is 8 20 times in a row with the same shifting (let's say it's 30), and let's look at output_num[32], [31] and [30]. The first time, you add 8 onto output_num[30], so these 3 are 0,0,8. Then you detect adding another 8 would make it bigger than 9, so you carry over onto output_num[31] and now you have 0,1,6. That's correct. But you don't carry over from output_num[31] onto output_num[32], so after adding a whole bunch of 8's, you get 0,10,4 instead of 1,0,4.

In your test you expected to get an output starting with 20313 but you got 110313 instead. That's because it's not 1,1,0,3,1,3 but actually 1,10,3,1,3. The 10 did not carry to the first digit in the output like it should have.

You could fix this by making the carrying into a loop, so it carries as many times as it needs to. You wouldn't need to do the inputDataRemainder and inputDataQuotient separately - you could just treat it all as remainder, then do the carry loop.

Or you can just let the digits get too high, then fix it at the end. You can just ignore the carrying when you add up the shifted numbers, and then before you print the number (or when you print it), you can see if the digit is bigger than 9, and then you take the quotient and remainder and add the quotient onto the next digit, and if that digit is bigger than 9 you do the same thing again, etc.

huangapple
  • 本文由 发表于 2023年3月3日 21:42:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/75627832.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定