s21_decimal @lucankri 12.02.2023 Смотрел недавно ролик на ютубе по этой теме, в целом довольно много интересных вещей говорит лектор, однако ошибки:
- 1:58:10 - "При переводе из дец в инт смотрим на
bits[1]
если там что-то есть то вовзращаем ошибку конвертации т.к число очень больше из-за того что у нас один элемент bits и есть int" С этим не согласен, у нас же есть еще коэфицент из-за которого мы можем заполнить хоть все 3 инта и понизить их с помощью степени до вполне входящего в диапазон целых чисел значения
Дебаггер совет
Хорошая настройка для дебаггера в VSCode (LLDB + CodeLLDB extension):type format add --format {n_system} '{data_type}'
Где
n_system
система счисления Двоичная
bin
Восьмеричная
oct
Десятичная
dec
Шестнадцатеричная
hex
А
data_type
тип данных, записанный в кавычках одинарных.Пример:
Смена отображения целочисленных переменных на двоичный вид:
type format add --format bin 'int'
Картинка из экселя которая поможет лучше представить как устроены данные в Decimal
По этой структуре предлагается написать программу:
typedef struct {
int bits[4];
} s21_decimal;
Посмотрев и поработав с этим проектом я считаю что чуть удобнее будет использовать unsigned int
, потому что в нем не резервируется первый бит для знака числа
typedef struct {
unsigned int bits[4];
} s21_decimal;
int s21_from_int_to_decimal(int src, s21_decimal *dst)
Если число положительное то кладем прямо так его в bits[0]
, если отрицательное инвертируем всего биты через ~
и прибавляем 1
тем самым мы избавимся от обратной дополненной записи и положим модуль числа. Еще если число входящее у нас отрицательное нужно выставить единицу в бите знака s21_decimal
, для этого можно просто присвоить bits[3]
значение равное единице.
int s21_from_float_to_decimal(float src, s21_decimal *dst)
int s21_from_decimal_to_int(s21_decimal src, int *dst)
int s21_from_decimal_to_float(s21_decimal src, float *dst)
int s21_add(s21_decimal value_1, s21_decimal value_2, s21_decimal *result)
Сложение строится на следующих вещах:
- Валидация входных значений
- Сложение мантисс
- Валидация суммы мантисс
- Изменение степени, в зависимости от незначащих нулей, например 0.5000
Note
Последовательность вычислений
Сначала проверка входных значений
Складываем 96 битов одного и 96 битов второго децимала в отдельную структуру где бы все это смогло поместиться
Затем смотрим на степень старушую и приписываем ее в децимал резульатата
После того как мы сложили в отдельную структуру наши мантиссы нам нужно провалидировать ее вычтя дополнительно степени десятки из степени децимала-резульата паралельно деля на степень десятки результат сложения мантисс.
Если наш результат сложения 96+96 мантисс не умещается даже после работы степени по отбрасыванию незначащих десяток, то
нужно пытаться поместить его в 96 битов деля на степень десятки, даже если после этого он не влез (степень превысила 28) то
кидаем ошибку оверфлоу!
int s21_sub(s21_decimal value_1, s21_decimal value_2, s21_decimal *result)
то же самое что сложение, только второй операнд нужно перевести в форму отрицательного числа и знак обработать
int s21_mul(s21_decimal value_1, s21_decimal value_2, s21_decimal *result)
int s21_div(s21_decimal value_1, s21_decimal value_2, s21_decimal *result)
int s21_is_less(s21_decimal, s21_decimal)
int s21_is_less_or_equal(s21_decimal, s21_decimal)
int s21_is_greater(s21_decimal, s21_decimal)
int s21_is_greater_or_equal(s21_decimal, s21_decimal)
int s21_is_equal(s21_decimal, s21_decimal)
int s21_is_not_equal(s21_decimal, s21_decimal)
int s21_floor(s21_decimal value, s21_decimal *result)
int s21_round(s21_decimal value, s21_decimal *result)
int s21_truncate(s21_decimal value, s21_decimal *result)
int s21_negate(s21_decimal value, s21_decimal *result)
От дани:)
Добавлю в понимание еще один логический оператор ^
или по другому XOR
, кому как удобнее.
Что бы было понятнее, ниже представленно результат работы:
1010 ^ 1100 = 0110
x ^ 1 = !x
x ^ 0 = x
Данную операцию намного удобнее использовать для инверсии нужного бита. Например для умножения на -1
достатачно выполнить bits[3] ^ (1 << 31)
.