diff --git a/12.Data-representation/CMakeLists.txt b/12.Data-representation/CMakeLists.txt new file mode 100644 index 0000000..24c18b8 --- /dev/null +++ b/12.Data-representation/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.10) +project("12.Internal-data-representation" C) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) + +# Task 1: Binary representation +add_executable(binary_converter + src/Task_1/main.c + src/Task_1/binary.c +) + +target_include_directories(binary_converter PRIVATE src/Task_1) +set_target_properties(binary_converter PROPERTIES OUTPUT_NAME "Binary_representation") + +# Task 2: Double under the microscope +add_executable(double_converter + src/Task_2/double.c +) + +target_include_directories(double_converter PRIVATE src/Task_2) +set_target_properties(double_converter PROPERTIES OUTPUT_NAME "Double_under_the_microscope") \ No newline at end of file diff --git a/12.Data-representation/src/Task_1/binary.c b/12.Data-representation/src/Task_1/binary.c new file mode 100644 index 0000000..0600df6 --- /dev/null +++ b/12.Data-representation/src/Task_1/binary.c @@ -0,0 +1,263 @@ +#include "binary.h" +#include +#include + +// Функция для вычисления степени числа +int power(int degree, int number) +{ + int result = 1; + + if (degree == 0) + { + return result; + } + + for (int i = 0; i < degree; i++) + { + result = result * number; + } + + return result; +} + +// Функция для нахождения длины переменной типа int +int length_int(int number) +{ + int count = 0; + + if (number == 0) + { + return 1; + } + + while (number != 0) + { + number = number / 10; + count++; + } + + return count; +} + +// Функция для перевода числа в двоичное представление +int binary_representation(int number) +{ + int binary[64]; + int intermediate = 0, result = 0, i = 0; + int bits = 16; + + // Если число 0 + if (number == 0) + { + printf("0"); + return 0; + } + + if (number > 1023) + { + printf("Внимание, число больше 1023, результат неправельный, введите " + "число меньше либо равное 1023\n"); + return 0; + } + + int original_number = number; + + // Обрабатываем отрицательные числа + if (number < 0) + { + unsigned int temp = -number; + + i = 0; + while (temp > 0) + { + binary[i] = temp % 2; + temp = temp / 2; + i++; + } + + while (i < bits) + { + binary[i] = 0; + i++; + } + + for (int j = 0; j < bits; j++) + { + if (binary[j] == 0) + { + binary[j] = 1; + } + else if (binary[j] == 1) + { + binary[j] = 0; + } + } + + int carry = 1; + for (int j = 0; j < bits; j++) + { + int sum = binary[j] + carry; + binary[j] = sum % 2; + carry = sum / 2; + if (carry == 0) + break; + } + } + + // Обрабатываем положительные числа + else if (number > 0) + { + i = 0; + while (number > 0) + { + binary[i] = number % 2; + number = number / 2; + i++; + } + + while (i < bits) + { + binary[i] = 0; + i++; + } + } + + // Собираем результат + for (int j = i - 1; j >= 0; j--) + { + intermediate = binary[j] * power(j, 10); + result = result + intermediate; + } + + return result; +} + +// Функция для перевода бинарного числа в десятичное +int decimal_representation(int binary) +{ + int result = 0; + int temp = binary; + int len = length_int(binary); + + // Проверка на корректность двоичного числа + for (int i = 0; i < len; i++) + { + int digit = temp % 10; + if (digit > 1) + { + printf("Ошибка: число %d не является двоичным!\n", binary); + return -1; + } + temp = temp / 10; + } + + // Преобразование + for (int i = 0; i < len; i++) + { + int digit = binary % 10; + result += digit * power(i, 2); + binary = binary / 10; + } + + return result; +} + +// Функция для сложения в столбик в двоичном представлении +int binary_addition(int binary_1, int binary_2) +{ + int length_1 = length_int(binary_1); + int length_2 = length_int(binary_2); + int final_length = 0; + + if (length_1 > length_2) + { + final_length = length_1; + } + else + { + final_length = length_2; + } + + // Создаем массивы с дополнительным местом для возможного переноса + int arr_1[final_length + 1]; + int arr_2[final_length + 1]; + int arr_sum[final_length + 2]; + + // Инициализируем массивы нулями + for (int i = 0; i <= final_length; i++) + { + arr_1[i] = 0; + arr_2[i] = 0; + } + + // Заполняем массивы с конца + int index_1 = final_length; + int temp_1 = binary_1; + while (temp_1 > 0) + { + arr_1[index_1] = temp_1 % 10; + temp_1 /= 10; + index_1--; + } + + int index_2 = final_length; + int temp_2 = binary_2; + while (temp_2 > 0) + { + arr_2[index_2] = temp_2 % 10; + temp_2 /= 10; + index_2--; + } + + // Выполняем сложение с переносом + int carry = 0; + int sum_index = final_length + 1; + + for (int i = final_length; i >= 0; i--) + { + int bit_sum = arr_1[i] + arr_2[i] + carry; + + if (bit_sum == 0) + { + arr_sum[sum_index] = 0; + carry = 0; + } + else if (bit_sum == 1) + { + arr_sum[sum_index] = 1; + carry = 0; + } + else if (bit_sum == 2) + { + arr_sum[sum_index] = 0; + carry = 1; + } + else + { + arr_sum[sum_index] = 1; + carry = 1; + } + sum_index--; + } + + // Обрабатываем оставшийся перенос + if (carry == 1) + { + arr_sum[sum_index] = 1; + } + else + { + arr_sum[sum_index] = 0; + } + + // Преобразуем массив обратно в число + int result = 0; + int start_index = (arr_sum[0] == 0 && final_length > 0) ? 1 : 0; + + for (int i = start_index; i <= final_length + 1; i++) + { + result = result * 10 + arr_sum[i]; + } + + return result; +} diff --git a/12.Data-representation/src/Task_1/binary.h b/12.Data-representation/src/Task_1/binary.h new file mode 100644 index 0000000..bf08fc3 --- /dev/null +++ b/12.Data-representation/src/Task_1/binary.h @@ -0,0 +1,14 @@ +#ifndef BINARY_H +#define BINARY_H + +int power(int degree, int number); + +int length_int(int number); + +int binary_representation(int number); + +int decimal_representation(int binary); + +int binary_addition(int binary_1, int binary_2); + +#endif diff --git a/12.Data-representation/src/Task_1/main.c b/12.Data-representation/src/Task_1/main.c new file mode 100644 index 0000000..84b1b4a --- /dev/null +++ b/12.Data-representation/src/Task_1/main.c @@ -0,0 +1,140 @@ +#include "binary.h" +#include +#include +#include +#include + +int main() +{ + printf("=== Двоичное представление === \n"); + + // Ввод чисел + char char_input_numbers[100]; + int int_input_numbers[100]; + + printf("\n"); + printf("Ведите число от 0 до 1023 для перевода в двоичный вид\n"); + printf("Введите два числа, сумма которых не превышает 1023, чтобы получить " + "их сумму в двоичном представлении\n"); + printf("\n"); + fgets(char_input_numbers, sizeof(char_input_numbers), stdin); + int len_numbers = strlen(char_input_numbers); + + for (int i = 0; i < len_numbers; i++) + { + if (char_input_numbers[i] >= '0' && char_input_numbers[i] <= '9') + { + int_input_numbers[i] = char_input_numbers[i] - '0'; + } + else + { + int_input_numbers[i] = -1; + } + } + + int num_1 = 0, num_2 = 0; + int count = 0, operations = 0; + + for (int i = 0; i < len_numbers; i++) + { + if (int_input_numbers[i] != -1) + { + count++; + } + + else + { + if (count > 0 && num_1 == 0) + { + while (count != 0) + { + operations + = int_input_numbers[i - count] * power(count - 1, 10); + num_1 = num_1 + operations; + count--; + } + continue; + } + + else if (count > 0 && num_2 == 0) + { + while (count != 0) + { + operations + = int_input_numbers[i - count] * power(count - 1, 10); + num_2 = num_2 + operations; + count--; + } + } + + else + { + printf("Ошибка. Введите только два числа через пробел\n"); + break; + } + } + } + + printf("\n"); + printf("Введены числа %d и %d \n", num_1, num_2); + + int number_1_translation, number_2_translation, binary_1_translation, + binary_2_translation, column_addition, column_addition_translation; + + // Перевод чисел в двоичное представление + if (num_1 < 1024 && num_2 < 1024) + { + printf("- Перевод числа в двоичное представление\n"); + number_1_translation = binary_representation(num_1); + number_2_translation = binary_representation(num_2); + printf("Число %d в двоичном представлении: %d\n", num_1, + number_1_translation); + printf("Число %d в двоичном представлении: %d\n", num_2, + number_2_translation); + printf("\n"); + } + + else + { + printf("Ошибка. Число больше 1023 будут содержать 11 и более битов, " + "что выходит за рамки предусмотренного формата\n"); + return 0; + } + + // Сложение в столбик в двоичном представлении, сумма + printf("- Сложение в столбик в двоичном представлении\n"); + if (num_1 + num_2 > 1023) + { + printf("Ошибка. Числа в сумме дают больше 1023 и будут содержать 11 и " + "более битов, что выходит за рамки предусмотренного формата\n"); + printf("\n"); + } + + else + { + column_addition + = binary_addition(number_1_translation, number_2_translation); + printf("Сложение %d и %d в столбик: %d\n", number_1_translation, + number_2_translation, column_addition); + printf("\n"); + } + + // Перевод в десятичное число + printf("- Перевод в десятичное число\n"); + binary_1_translation = decimal_representation(number_1_translation); + binary_2_translation = decimal_representation(number_2_translation); + column_addition_translation = decimal_representation(column_addition); + printf("Число %d в десятичном представлении: %d\n", number_1_translation, + binary_1_translation); + printf("Число %d в десятичном представлении: %d\n", number_2_translation, + binary_2_translation); + if (num_1 + num_2 < 1023) + { + printf("Сумма %d в десятичном представлении: %d\n", column_addition, + column_addition_translation); + } + + printf("\n \n"); + + return 0; +} diff --git a/12.Data-representation/src/Task_2/double.c b/12.Data-representation/src/Task_2/double.c new file mode 100644 index 0000000..954c1ab --- /dev/null +++ b/12.Data-representation/src/Task_2/double.c @@ -0,0 +1,76 @@ +#include +#include + +int main() +{ + union + { + double d; + uint64_t u; + } num; + + printf("Введите число: "); + scanf("%lf", &num.d); + + // Извлекаем биты + uint64_t bits = num.u; + int sign = (bits >> 63) & 1; + int exponent = (bits >> 52) & 0x7FF; + uint64_t mantissa = bits & 0xFFFFFFFFFFFFF; + + // Специальные случаи + if (exponent == 0x7FF) + { + if (mantissa == 0) + { + printf("%cinf\n", sign ? '-' : '+'); + } + + else + { + printf("NaN\n"); + } + return 0; + } + + // Вычисляем порядок + int power; + if (exponent == 0) + { + if (mantissa == 0) + { + printf("%c0.0*2^0\n", sign ? '-' : '+'); + return 0; + } + power = -1022; + while (!(mantissa & (1ULL << 51))) + { + mantissa <<= 1; + power--; + } + mantissa <<= 1; + mantissa &= 0xFFFFFFFFFFFFF; + } + + else + { + power = exponent - 1023; + mantissa |= 1ULL << 52; + } + + // Выводим знак + printf("%c1.", sign ? '-' : '+'); + + // Выводим мантиссу с 20 знаками после запятой + uint64_t remainder = mantissa & ((1ULL << 52) - 1); + for (int i = 0; i < 20; i++) + { + remainder *= 10; + printf("%lu", remainder >> 52); + remainder &= (1ULL << 52) - 1; + } + + printf("*2^%d\n", power); + + return 0; +}