Пытаюсь реализовать функции сложения, вычитания, умножения и деления для структуры decimal, в общем как оригинальная библиотека, только у меня число не превышает 96 разряд, то есть у числа экспонента не выше 28
(это так для справки). Структура выглядит таким образом:
typedef struct {
unsigned int bits[4];
} decimal;
Создал я два числа decimal num1 = {{45,55,0,0}}; decimal num2 = {{6,20,0,0}}, и хочу их умножить, чтобы получить в ответе 2 824 100, если бы была экспонента, то просто число представляло такой вид: decimal/10^exp. В одном объяснение предлагалось взять первое число = num1.bits[i], проходится побитово по нему, и если там 1, то к сумме прибавлять результат сдвига второго числа на индекс бита первого, то есть sum += num2.bits[i] * 2^j
(sum += num2.bits[i] << j). Я попробовал сделать двумя представлениями, однако получаю либо число 2 701 370 137, а структура ответа выглядит таким образом decimal result = {{270, 1370, 1370,0}}, либо просто 200 decimal result = {{20, 0, 0,48}} (полная ерунда). Я так понимаю, проблема в том, что мне нужно учитывать переход одного разряда в другой, и делать правильное сложение и заполнение всей мантисы
Вот код умножения:
int mul(decimal value_1, decimal value_2, decimal *result)
{
int ret = 0;
*result = (decimal){0};
decimal res = {0};
int sum = 0;
for (int i = 0; i < 3; i++)
{
int a = value_1.bits[i];
int b = value_2.bits[i];
for (int i = 0; i < 32; i++)
{
int bit = (a & (1u << i)) >> i;
if (bit == 1)
{
sum += b * pow(2,i);//тут простое мат. умножение и в результате каждый int умножается правилно, но общее число не корректно
// res.bits[i] += b << i;//здесь я сделал попытку побитово умножать, но делаю это заведомо неправильно
}
}
printf("SUM: %d\n",sum);
res.bits[i] = sum;
printf("\n");
}
int sign = sign_1 ^ sign_2;
*result = res;
set_sign(result, sign);
return ret;
}
Вот код сложения:
int add(decimal value_1, decimal value_2, decimal *result)
{
ret = decimal_normalize(&value_1, &value_2);//нормализация, то есть если у одного числа экспонента больше, то я у другог увелчиваю ее пока они не станут равны и умножаю его на 10
if (sign1 == sign2)
{
for (int i = 0; i < 3; i++)
{
result->bits[i] = value_1.bits[i] + value_2.bits[i];//просто складываю числа, если знаки равны
}
ret = 0;
}
else
{
decimal temp1 = {0};
decimal temp2 = {0};
if (sign1 == 1)
{
temp1 = value_1;
invert_bit(&temp1.bits[3], 31);//инверитрую бит, то есть меняю знак
temp2 = value_2;
}
else
{
temp2 = value_2;
invert_bit(&temp2.bits[3], 31);//инверитрую бит, то есть меняю знак
temp1 = value_1;
}
if (is_less(temp1, temp2))//здесь проверка какой число пол. и отриц. 1 приходит в случае, если temp1 отрицательно, а temp2 пол. или если tepm1 больше мантисой при отриц. знаке или если temp1 меньше при положительном
{
decimal copy = value_2;
int carry = 0;
for (int i = 0; i < 3; i++)
{
copy.bits[i] += carry ? ~(value_1.bits[i] + 1) + 1 : ~value_1.bits[i] + 1;
carry = 0;
if (value_2.bits[i] < value_1.bits[i])
{
carry = 1;
}
}
*result = copy;
sign1 = 0;
}
else
{
decimal copy = value_1;
int carry = 0;
for (int i = 0; i < 3; i++)
copy.bits[i] += carry ? ~(value_2.bits[i] + 1) + 1 : ~value_2.bits[i] + 1;
carry = 0;
if (value_1.bits[i] < value_2.bits[i])
{
carry = 1;
}
}
*result = copy;
sign2 = 0;
}
}
int sign = sign1 | sign2;
set_sign(result, sign);//ставит нужный знак числу, то есть делает decimal = {{1,2,3,-2147483648}} или если положительный не трогает
return ret;
}