Реализация собственной библиотеки decimal.h.
Двоичное представление Decimal состоит из 1-разрядного знака, 96-разрядного целого числа и коэффициента масштабирования, используемого для деления целого числа и указания того, какая его часть является десятичной дробью. Коэффициент масштабирования неявно равен числу 10, возведенному в степень в диапазоне от 0 до 28.
Decimal число может быть реализовано в виде четырехэлементного массива 32-разрядных целых чисел со знаком (int bits[4];).
bits[0], bits[1], и bits[2] содержат младшие, средние и старшие 32 бита 96-разрядного целого числа соответственно.
bits[3] содержит коэффициент масштабирования и знак, и состоит из следующих частей:
- Биты от 0 до 15, младшее слово, не используются и должны быть равны нулю.
- Биты с 16 по 23 должны содержать показатель степени от 0 до 28, который указывает степень 10 для разделения целого числа.
- Биты с 24 по 30 не используются и должны быть равны нулю.
- Бит 31 содержит знак; 0 означает положительный, а 1 означает отрицательный.
Обрати внимание, что битовое представление различает отрицательные и положительные нули. Эти значения могут считаться эквивалентными во всех операциях.
typedef struct
{
int bits[4];
} decimal;| Название оператора | Оператор | Функция |
|---|---|---|
| Сложение | + | int add(decimal value_1, decimal value_2, decimal *result) |
| Вычитание | - | int sub(decimal value_1, decimal value_2, decimal *result) |
| Умножение | * | int mul(decimal value_1, decimal value_2, decimal *result) |
| Деление | / | int div(decimal value_1, decimal value_2, decimal *result) |
Функции возвращают код ошибки:
- 0 — OK;
- 1 — число слишком велико или равно бесконечности;
- 2 — число слишком мало или равно отрицательной бесконечности;
- 3 — деление на 0.
Уточнение про числа, не вмещающиеся в мантиссу:
- При получении чисел, не вмещающихся в мантиссу при арифметических операциях, использовать банковское округление (например, 79,228,162,514,264,337,593,543,950,335 — 0.6 = 79,228,162,514,264,337,593,543,950,334).
| Название оператора | Оператор | Функция |
|---|---|---|
| Меньше | < | int is_less(decimal, decimal) |
| Меньше или равно | <= | int is_less_or_equal(decimal, decimal) |
| Больше | > | int is_greater(decimal, decimal) |
| Больше или равно | >= | int is_greater_or_equal(decimal, decimal) |
| Равно | == | int is_equal(decimal, decimal) |
| Не равно | != | int is_not_equal(decimal, decimal) |
Возвращаемое значение:
- 0 — FALSE;
- 1 — TRUE.
| Преобразователь | Функция |
|---|---|
| Из int | int from_int_to_decimal(int src, decimal *dst) |
| Из float | int from_float_to_decimal(float src, decimal *dst) |
| В int | int from_decimal_to_int(decimal src, int *dst) |
| В float | int from_decimal_to_float(decimal src, float *dst) |
Возвращаемое значение — код ошибки:
- 0 — OK;
- 1 — ошибка конвертации.
Уточнение про преобразование числа типа float:
- Если числа слишком малы (0 < |x| < 1e-28), вернуть ошибку и значение, равное 0.
- Если числа слишком велики (|x| > 79,228,162,514,264,337,593,543,950,335) или равны бесконечности, вернуть ошибку.
- При обработке числа с типом float преобразовывать все содержащиеся в нём значимые десятичные цифры. Если таких цифр больше 7, то значение числа округляется к ближайшему, у которого не больше 7 значимых цифр.
Уточнение про преобразование из числа типа decimal в тип int:
- Если в числе типа decimal есть дробная часть, то её следует отбросить (например, 0.9 преобразуется 0).
| Описание | Функция |
|---|---|
| Округляет указанное Decimal число до ближайшего целого числа в сторону отрицательной бесконечности. | int floor(decimal value, decimal *result) |
| Округляет Decimal до ближайшего целого числа. | int round(decimal value, decimal *result) |
| Возвращает целые цифры указанного Decimal числа; любые дробные цифры отбрасываются, включая конечные нули. | int truncate(decimal value, decimal *result) |
| Возвращает результат умножения указанного Decimal на -1. | int negate(decimal value, decimal *result) |
Возвращаемое значение — код ошибки:
- 0 — OK;
- 1 — ошибка вычисления.