乘两个数组为int值 [英] multiply two arrays with int values

查看:165
本文介绍了乘两个数组为int值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有 N1 N2 我想将它们相乘
比如我有阵

suppose I have n1 and n2 I want to multiply them for example I have array

n1={1,2,3};

n2={5,6}   

他们是在两个整数N1 有一个 123 N2 56

123*56=6888

然后结果我应该有

then in result I should have

result = {6,8,8,8}    

下面是我想不完全算法

for(i in n1 bigger array)
    for(j in n2 smaller one)
    {
        mult=n1[i]*n2[j]
        mult+= carry;

        if(mult>=10)
        {
            carry = (mult/10);
            mult-= (carry*10);
        }
    }
}

我怎么能写呢?我不知道店的地方
完成内幕循环之后我应该存储在NUM阵列,然后再计算和...
我应该怎么写呢?我找遍了整个溢出这里,但我并没有在C code找到它

How can I write it? I don't know the place of store after finishing the insider loop I should store num in array and then compute again and... How should I write it? I searched the whole of overflow here but I didn't find about it in c code

目标是计算大量的整数数字有 8个字节,换句话说,64位,使他们能够存储 2pow64-1 19位现在这将有助于计算超过19位。

The Goal is to Compute the Large numbers Integer Numbers has 8 Bytes,in other words 64 bits so they can store 2pow64-1 which is 19 digits now this will help to compute very larger than 19 digits

推荐答案

这将是,如果你的数字阵列是小端稍微容易些。然后你的榜样乘法看起来

It would be slightly easier if your digit-arrays were little-endian. Then your example multiplication would look

 3  2  1 * 6 5
---------------
18 12  6
   15 10  5
---------------
18 27 16  5    // now propagate carries
 8 28 16  5
 8  8 18  5
 8  8  8  6
============

的N1产品[I] N2 [J] 将有助于结果[I + J] 。主循环大致可以看起来像

The product of n1[i] and n2[j] would contribute to result[i+j]. The main loop could roughly look like

for (i = 0; i < l1; ++i) // l1 is length of n1
{
    for (j = 0; j < l2; ++j) // l2 is length of n2
    {
        result[i+j] += n1[i]*n2[j];
    }
}
// now carry propagation

您看到的结果必须至少(L1-1)+(L2-1)+ 1 长,因为最显著位的产品去INT 结果[(L1-1)+(L2-1)] 。在另一方面, N1&LT; 10 ^ L1 N2&LT; 10 ^ 12 ,因此产品&LT; 10 ^(L1 + L2),你需要最多 L1 + L2 数字。结果
但是,如果你正在使用字符工作(符号或无符号),这将很快溢出每个数字,因为(对 K&LT; =分钟( L1-1,L2-1) K + 1 的两位数字产品(每个人都可以像81一样大)有助于数字<$ ç$ C> K 产品。

You see that the result must be at least (l1-1) + (l2-1) + 1 long, since the product of the most significant digits goes int result[(l1-1) + (l2-1)]. On the other hand, n1 < 10^l1 and n2 < 10^l2, so the product is < 10^(l1+l2) and you need at most l1+l2 digits.
But if you're working with char (signed or unsigned), that will quickly overflow in each digit, since (for k <= min(l1-1,l2-1)) k+1 products of two digits (each can be as large as 81) contribute to digit k of the product.

所以最好执行根据结果数字分组乘法,在一个更​​大的类型积累,并在写作的结果做数位进位传播。随着小尾数号

So it's better to perform the multiplication grouped according to the result digit, accumulating in a larger type, and doing carry propagation on writing the result digit. With little-endian numbers

char *mult(char *n1, size_t l1, char *n2, size_t l2, size_t *rl)
{
    // allocate and zero-initialise, may be one more digit than needed
    char *result = calloc(l1+l2+1,1);
    *rl = l1 + l2;
    size_t k, i, lim = l1+l2-1;
    for (k = 0; k < lim; ++k)
    {
        unsigned long accum = result[k];
        for (i = (k < l2) ? 0 : k-(l2-1); i <= k && i < l1; ++i)
        {
            accum += (n1[i] - '0') * (n2[k-i] - '0');
        }
        result[k] = accum % 10 + '0';
        accum /= 10;
        i = k+1;
        while(accum > 0)
        {
            result[i] += accum % 10;
            accum /= 10;
            ++i;
        }
    }
    if (result[l1+l2-1] == 0)
    {
        *rl -= 1;
        char *real_result = calloc(l1+l2,1);
        for (i = 0; i < l1+l2-1; ++i)
        {
            real_result[i] = result[i];
        }
        free(result);
        return real_result;
    }
    else
    {
        result[l1+l2-1] += '0';
        return result;
    }
}

有关大端号,索引必须进行修改 - 你能明白这一点你自己,有希望 - 但原理是一样的。

For big-endian numbers, the indexing has to be modified - you can figure that out yourself, hopefully - but the principle remains the same.

事实上,结果不是用铅笔和纸跟踪指数后,很多不同的:

Indeed, the result isn't much different after tracking indices with pencil and paper:

char *mult(char *n1, size_t l1, char *n2, size_t l2, size_t *rl)
{
    // allocate and zero-initialise, may be one more digit than needed
    // we need (l1+l2-1) or (l1+l2) digits for the product and a 0-terminator
    char *result = calloc(l1+l2+1,1);
    *rl = l1 + l2;
    size_t k, i, lim = l1+l2-1;
    // calculate the product from least significant digit to
    // most significant, least significant goes into result[l1+l2-1],
    // the digit result[0] can only be nonzero by carry propagation.
    for (k = lim; k > 0; --k)
    {
        unsigned long accum = result[k]; // start with carry
        for (i = (k < l2) ? 0 : k-l2; i < k && i < l1; ++i)
        {
            accum += (n1[i] - '0') * (n2[k-1-i] - '0');
        }
        result[k] = accum % 10 + '0';
        accum /= 10;
        i = k-1;
        while(accum > 0)
        {
            result[i] += accum % 10;
            accum /= 10;
            --i;
        }
    }
    if (result[0] == 0) // no carry in digit 0, we allocated too much
    {
        *rl -= 1;
        char *real_result = calloc(l1+l2,1);
        for (i = 0; i < l1+l2-1; ++i)
        {
            real_result[i] = result[i+1];
        }
        free(result);
        return real_result;
    }
    else
    {
        result[0] += '0'; // make it an ASCII digit
        return result;
    }
}

编辑:添加0终结

added 0-terminators

请注意:这些都不是 NUL 封端的(无符号)字符阵列,所以我们必须保持长度信息(这是很好做的工作),因此这将是更好地共同存储的信息与一个结构数字数组。此外,由于写它仅适用于正数。与负数打交道是尴尬的,如果你只有原始的数组,所以另一点用于存储其他信息。

Note: these are not NUL-terminated (unsigned) char arrays, so we need to keep length information (that's good to do anyway), hence it would be better to store that info together with the digit array in a struct. Also, as written it only works for positive numbers. Dealing with negative numbers is awkward if you only have raw arrays, so another point for storing additional info.

保持位数为 0 +值不会使该计算意义上说,它是只用于打印方便,但只有当他们是 NUL 封端阵列。您可能需要增加一个插槽的 NUL 终止子即可。在这种情况下,参数 RL 其中我们存储产品的长度不是严格必要的。

Keeping the digits as '0' + value doesn't make sense for the computations, it is only convenient for printing, but that only if they were NUL-terminated arrays. You may want to add a slot for the NUL-terminator then. In that case, the parameter rl in which we store the length of the product is not strictly necessary.

这篇关于乘两个数组为int值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆