Чтобы повысить скорость добавления bignum, вы должны упаковать больше десятичных цифр в элементы массива. Например: вы можете использовать uint32_t
вместо unsigned char
и хранить 9 цифр за раз.
Еще один прием для повышения производительности - избегать ветвлений.
Вот измененный версия вашего кода без тестов:
void LongNumAddition1(const char *Vin1, const char *Vin2, char *Vout, unsigned N) {
char carry = 0;
for (int i = 0; i < N; i++) {
char r = Vin1[i] + Vin2[i] + CARRY;
carry = (r >= 10);
Vout[i] = r - carry * 10;
}
}
Вот модифицированная версия, имеющая дело с 9 цифрами одновременно:
#include <stdint.h>
void LongNumAddition1(const uint32_t *Vin1, const uint32_t *Vin2, uint32_t *Vout, unsigned N) {
uint32_t carry = 0;
for (int i = 0; i < N; i++) {
uint32_t r = Vin1[i] + Vin2[i] + CARRY;
carry = (r >= 1000000000);
Vout[i] = r - carry * 1000000000;
}
}
Вы можете посмотреть код, сгенерированный g cc и включите компилятор GodBolt .
Вот небольшая тестовая программа:
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
int LongNumConvert(const char *s, uint32_t *Vout, unsigned N) {
unsigned i, len = strlen(s);
uint32_t num = 0;
if (len > N * 9)
return -1;
while (N * 9 > len + 8)
Vout[--N] = 0;
for (i = 0; i < len; i++) {
num = num * 10 + (s[i] - '0');
if ((len - i) % 9 == 1) {
Vout[--N] = num;
num = 0;
}
}
return 0;
}
int LongNumPrint(FILE *fp, const uint32_t *Vout, unsigned N, const char *suff) {
int len;
while (N > 1 && Vout[N - 1] == 0)
N--;
len = fprintf(fp, "%"PRIu32"", Vout[--N]);
while (N > 0)
len += fprintf(fp, "%09"PRIu32"", Vout[--N]);
if (suff)
len += fprintf(fp, "%s", suff);
return len;
}
void LongNumAddition(const uint32_t *Vin1, const uint32_t *Vin2,
uint32_t *Vout, unsigned N) {
uint32_t carry = 0;
for (unsigned i = 0; i < N; i++) {
uint32_t r = Vin1[i] + Vin2[i] + carry;
carry = (r >= 1000000000);
Vout[i] = r - carry * 1000000000;
}
}
int main(int argc, char *argv[]) {
const char *sa = argc > 1 ? argv[1] : "123456890123456890123456890";
const char *sb = argc > 2 ? argv[2] : "2035864230956204598237409822324";
#define NUMSIZE 111 // handle up to 999 digits
uint32_t a[NUMSIZE], b[NUMSIZE], c[NUMSIZE];
LongNumConvert(sa, a, NUMSIZE);
LongNumConvert(sb, b, NUMSIZE);
LongNumAddition(a, b, c, NUMSIZE);
LongNumPrint(stdout, a, NUMSIZE, " + ");
LongNumPrint(stdout, b, NUMSIZE, " = ");
LongNumPrint(stdout, c, NUMSIZE, "\n");
return 0;
}