C大数乘法
C big number multiplication
我试图为我的第一个测试编写一个大整数乘法,但如果 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;;
}
}
至少有 1 个问题:
在 c[]
中溢出
c[i+j+1] += A;
可能溢出 c[]
。
// 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;
}
尝试使用此代码
#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;
}```
我试图为我的第一个测试编写一个大整数乘法,但如果 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;;
}
}
至少有 1 个问题:
在 c[]
c[i+j+1] += A;
可能溢出 c[]
。
// 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;
}
尝试使用此代码
#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;
}```