У меня есть четыре беззнаковых 32-битных целых числа, представляющих беззнаковое 128-битное целое число в обратном порядке:
typedef struct {
unsigned int part[4];
} bigint_t;
Я хотел бы преобразовать это число в его десятичное строковое представление и вывести его в файл.
Прямо сейчас я использую функцию bigint_divmod10
, чтобы разделить число на 10, отслеживая остаток. Я вызываю эту функцию несколько раз, выводя остаток в виде цифры, пока число не станет нулевым. Это довольно медленно. Это самый быстрый способ сделать это? Если да, то есть ли хитрый способ реализовать эту функцию, которого я не вижу? Я пробовал смотреть get_str.c
GMP, но мне это непонятно.
РЕДАКТИРОВАТЬ: вот самый быстрый код, который я смог придумать для функции divmod10:
static unsigned uint128_divmod10(uint128 *value)
{
unsigned int a = value->word[3];
unsigned int b = value->word[2];
unsigned int c = value->word[1];
unsigned int d = value->word[0];
unsigned int diva = a / 5;
unsigned int divb = b / 5;
unsigned int divc = c / 5;
unsigned int divd = d / 5;
value->word[3] = diva;
value->word[2] = divb;
value->word[1] = divc;
value->word[0] = divd;
unsigned int moda = a - diva*5;
unsigned int modb = b - divb*5;
unsigned int modc = c - divc*5;
unsigned int modd = d - divd*5;
unsigned int mod = 0;
mod += moda;
unsigned int carryb = mod*858993459;
mod += modb;
if (mod >= 5) {
mod -= 5;
carryb++;
}
unsigned int carryc = mod*858993459;
mod += modc;
if (mod >= 5) {
mod -= 5;
carryc++;
}
unsigned int carryd = mod*858993459;
mod += modd;
if (mod >= 5) {
mod -= 5;
carryd++;
}
uint128_add(value, carryd, 0);
uint128_add(value, carryc, 1);
uint128_add(value, carryb, 2);
if (value->word[0] & 1) {
mod += 5;
}
uint128_shift(value, -1);
return mod;
}
где функция добавления определяется как:
static void uint128_add(uint128 *value, unsigned int k, unsigned int pos)
{
unsigned int a = value->word[pos];
value->word[pos] += k;
if (value->word[pos] < a) {
// overflow
for (int i=pos+1; i<4; i++) {
value->word[i]++;
if (value->word[i]) {
break;
}
}
}
}