I need to use uint64_t as unsigned long long int due to the fact that I need to fit in numbers larger than unsigned long in it? (both OSes are 64-bit), how can I fix this? Here is the code which impleements binary division:
Here is the function where I tried to print to see the result of the final function:
void binary_div(s21_big_decimal *value_1, s21_big_decimal value_2, s21_big_decimal *result) {
init_s21_decimal(result);
s21_big_decimal Q;
s21_big_decimal R;
int scaleDiv = -1;
do {
init_s21_decimal(&R);
init_s21_decimal(&Q);
scaleDiv++;
int lastBit = (SIZE_BIG_DECIMAL - 1) * 32 - 1;
int currentBit = get_bit_big(*value_1, lastBit);
while (currentBit == 0 && lastBit >= 0) {
currentBit = get_bit_big(*value_1, lastBit);
if (currentBit == 0) lastBit--;
}
for (int i = lastBit; i >= 0; i--) {
change_left_big(&R, 1);
set_bit_big(&R, 0, get_bit_big(*value_1, i));
if (is_less_or_equal_big(value_2, R)) {
s21_big_decimal res = {0};
init_s21_decimal(&res);
s21_sub_big(R, value_2, &res);
init_s21_decimal(&R);
copy_bits(res, &R);
set_bit_big(&Q, i, 1);
}
}
if (scaleDiv > 0) {
mul_10_big(result);
}
s21_big_decimal res;
init_s21_decimal(&res);
add_big(*result, Q, &res);
copy_bits(res, result);
if (!is_zero_big(R)) {
init_s21_decimal(value_1);
mul_10_big(&R);
copy_bits(R, value_1);
}
} while (!is_zero_big(R) && scaleDiv < 28);
set_scale_big(result, scaleDiv);
for (int i = 0; i < 7; i++) {
printf("%lX ", result->bits[i]);
}
printf("\n");
}
I work with bits here is example of the function mul_10_big:
int mul_10_big(s21_big_decimal *dec)
{
s21_big_decimal temp = *dec;
for (int i = 0; i < SIZE_BIG_DECIMAL - 1; i++)
{
temp.bits[i] *= 10;
}
temp.scale++;
int overflowed = 0;
if (getoverflow(&temp))
{
overflowed = 1;
}
else
{
*dec = temp;
}
return overflowed;
}
int div_10_big(s21_big_decimal *dec)
{
uint64_t remained = 0;
for (int i = SIZE_BIG_DECIMAL - 2; i >= 0; i--)
{
dec->bits[i] += remained << 32;
remained = dec->bits[i] % 10;
dec->bits[i] /= 10;
}
dec->scale--;
return remained;
}
int add_big(s21_big_decimal big_dec1, s21_big_decimal big_dec2,
s21_big_decimal *result)
{
int res = 0;
normalization_big(&big_dec1, &big_dec2);
for (int i = 0; i < SIZE_BIG_DECIMAL - 1; i++)
{
result->bits[i] += big_dec1.bits[i] + big_dec2.bits[i];
getoverflow(result);
}
return res;
}
uint64_tisunsigned longon linux and macOS because the typeunsigned longhas 64 bits so there is no need to use a type with a larger rank such asunsigned long longeventhough this later type also has 64 bits.On Windows,
uint64_tcannot be typedefed tounsigned longbecause for legacy reasons, Microsoft chose to keepunsigned longas a 32-bit type even on its 64-bit ABIs.If you need to handle numbers larger than
4294967295, you should indeed not useunsigned longthat may be limited to 32 bits. Usinguint64_tthat has exactly 64 bits orunsigned long longthat has at least 64 bits are the correct choices.uint64_tmight not be available on all platforms, but is on your targets and you are unlikely to ever encounter one that does not.Whether
uint64_tis typedefed tounsigned longorunsigned long longdoes not matter for your purpose as it always has 64 bits.Changing the type
uint64_tis not an option as you will get potential undefined behavior using different definitions in different modules.If you use integer types consistently in your application, using
uint64_teverywhere you need a 64-bit unsigned type should not pose a problem.For reading and printing, you can either use the standard macros defined in
<inttypes.h>:If you prefer, you can use
strtoullandprintfthis way:You could also define your own type
u64_tas a typedef forunsigned long longand use%lluor%llxinscanfandprintflike functions without extra casts.Or you can simply use
unsigned long longeverywhere.