[英]How can I multiply a 64-bit unsigned int with a 32-bit unsigned int on C without using long long?
How can I multiply a 64-bit unsigned int with a 32-bit unsigned int without using long long
. 如何在不使用
long long
情况下将64位unsigned int与32位unsigned int相乘。 The 64-bit number is stored as an array of two 32-bit numbers. 64位数字存储为两个32位数字的数组。
In other words, how I can I obtain e
and f
from a
, b
and c
given the following: 换句话说,在以下条件下,我如何从
a
, b
和c
获得e
和f
:
( a * 2^32 + b ) * c = e * 2^32 + f
a
, b
, c
, e
and f
are all 32-bit unsigned integers, and only 32-bit math operations are available. a
, b
, c
, e
和f
均为32位无符号整数,并且仅32位数学运算可用。
The first thing to realize is that we'll obtain a 96-bit number, as the following shows: 首先要意识到的是,我们将获得一个96位的数字,如下所示:
(2 64 - 1) × (2 32 - 1) (2 64-1 )×(2 32-1 )
= 2 64 × 2 32 - 2 64 - 2 32 + 1 = 2 64 ×2 32-2 64-2 32 +1
= 2 96 - 2 64 - 2 32 + 1 = 2 96 - 2 64 - 2 32 + 1
< 2 96 <2 96
The next thing to realize is that we can't use 32-bit multiplication. 接下来要意识到的是,我们不能使用32位乘法。 Even without a carry, the results are too large.
即使没有进位,结果也太大。
(2 32 - 1) × (2 32 - 1) (2 32-1 )×(2 32-1 )
= 2 32 × 2 32 - 2 32 - 2 32 + 1 = 2 32 ×2 32-2 32-2 32 +1
= 2 64 - 2 33 + 1 = 2 64-2 33 +1
≥ 2 32 ≥2 32
We'll need to perform 16-bit multiplications instead. 我们将需要执行16位乘法。 16-bit multiplication can be done using 32-bit numbers without the possibility of overflow, even with a 16-bit carry.
即使使用16位进位,也可以使用32位数字完成16位乘法运算而不会发生溢出。
FFFF 16 × FFFF 16 + FFFF 16 FFFF 16 ×FFFF 16 + FFFF 16
= FFFF_0000 16 = FFFF_0000 16
< 2 32 <2 32
If we view the numbers as 16-bit values, the multiplication looks like: 如果我们将数字视为16位值,则乘法看起来像:
+-----+-----+-----+-----+
| ahi | alo | bhi | blo |
+-----+-----+-----+-----+
+-----+-----+
× | chi | clo |
+-----+-----+
===========================================
+-----+-----+-----+-----+-----+-----+
| dhi | dlo | ehi | elo | fhi | flo |
+-----+-----+-----+-----+-----+-----+
We all know how to do the above multiplication from elementary school, right? 我们都从小学知道如何进行上述乘法,对吗?
+-----+-----+-----+-----+ +-----+
| ahi | alo | bhi | blo | × | clo |
+-----+-----+-----+-----+ +-----+
+-----+-----+-----+-----+-----+ +-----+
+ | ahi | alo | bhi | blo | 0 | × | chi |
+-----+-----+-----+-----+-----+ +-----+
The means the following are all the tools we need: 这意味着以下是我们需要的所有工具:
void mul16c(
uint16_t i, uint16_t j, uint16_t cin,
uint16_t *prod_ptr, uint16_t *cout_ptr
) {
uint32_t prod = i * j + cin;
*prod_ptr = prod & 0xFFFF:
*cout_ptr = prod >> 16;
}
void add16c(
uint16_t i, uint16_t j, uint16_t cin,
uint16_t *sum_ptr, uint16_t* cout_ptr
) {
uint32_t sum = i + j + cin;
*sum_ptr = sum & 0xFFFF:
*cout_ptr = sum >> 16;
}
And we can use them as follows: 我们可以如下使用它们:
void mul64x32(
uint32_t i[2], uint32_t j,
uint32_t (*prod_ptr)[2], uint32_t *cout_ptr
) {
uint16_t i16[4];
i16[3] = i[1] >> 16;
i16[2] = i[1] & 0xFFFF;
i16[1] = i[0] >> 16;
i16[0] = i[0] & 0xFFFF;
uint16_t j16[2];
j16[1] = j[0] >> 16;
j16[0] = j[0] & 0xFFFF;
uint16_t p[6];
{
uint16_t carry = 0;
mul16c(i16[0], j16[0], carry, &(p[0]), &carry);
mul16c(i16[1], j16[0], carry, &(p[1]), &carry);
mul16c(i16[2], j16[0], carry, &(p[2]), &carry);
mul16c(i16[3], j16[0], carry, &(p[3]), &carry);
p[4] = carry;
p[5] = 0;
}
uint16_t q[6];
{
uint16_t carry = 0;
q[0] = 0;
mul16c(i16[0], j16[1], carry, &(q[1]), &carry);
mul16c(i16[1], j16[1], carry, &(q[2]), &carry);
mul16c(i16[2], j16[1], carry, &(q[3]), &carry);
mul16c(i16[3], j16[1], carry, &(q[4]), &carry);
q[5] = carry;
}
uint16_t product[6];
{
uint16_t carry = 0;
add16c(p[0], q[0], carry, &(product[0]), &carry);
add16c(p[1], q[1], carry, &(product[1]), &carry);
add16c(p[2], q[2], carry, &(product[2]), &carry);
add16c(p[3], q[3], carry, &(product[3]), &carry);
add16c(p[4], q[4], carry, &(product[4]), &carry);
add16c(p[5], q[5], carry, &(product[5]), &carry);
}
(*prod_ptr)[0] = ( product[1] << 16 ) | product[0];
(*prod_ptr)[1] = ( product[3] << 16 ) | product[2];
*cout_ptr = ( product[5] << 16 ) | product[4];
}
Element zero of each array is expected to be the least significant portion of the number. 每个数组的元素零应该是数字的最低有效部分。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.