Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #define ERROR_CODE -1
- #define RIGHT 0
- #define INPUT_OK 1
- #define ALLOWED_INPUT_SIZE 38
- #define SIGN_QUANTITY_LIMIT 2
- #define DEGREE_LIMIT 1
- #define DOT_LIMIT 1
- #define POSITIVE_NUMBER 1
- #define NEGATIVE_NUMBER -1
- #define TRUE 1
- #define FALSE 0
- #define DIGITS_SIZE 30
- struct BigDecimal
- {
- int size;
- int digits[DIGITS_SIZE];
- int E;
- int sign;
- };
- /*1)Смоделировать операцию деления действительного числа
- на действительное число в форме (+,-)m.n Е (+,-)K, где
- суммарная длина мантиссы (m+n) - до 30 значащих цифр, а
- величина порядка K - до 5 цифр. Результат выдать в форме
- (+,-)0.m1 Е (+,-)K1, где m1 - до 30 значащих цифр, а K1 - до 5
- цифр.
- *
- * */
- void welcome_text()
- {
- printf("This program performs the operation of dividing real numbers \n"
- "Data entry begins strictly with the sign of the number(+ or -) \n"
- "If there is degree in number, then the sign of degree (+ or"
- " -) is also indicated strictly after E \n"
- "If you enter E, there should be no spaces between numbers and E \n"
- "The number entered must not exceed 30 characters \n"
- "The size of the input degree must not exceed 5 characters \n"
- "Real numbers must be entered through a dot \n"
- " 1 15 30\n"
- " |-------------|--------------|\n");
- }
- void swap(int *xp, int *yp)/*Функция, меняющая местами числа*/
- {
- int temp = *xp;
- *xp = *yp;
- *yp = temp;
- }
- void printArrayResult(int *res, int size)
- {
- for (int j = 0; j < size; j++)
- {
- printf("%d,", res[j]);
- }
- printf("\n");
- }
- void printNumber(int num)
- {
- printf("Number = %d\n", num);
- }
- void printBigDecimal(struct BigDecimal val)
- {
- printf("Size=%d, E=%d, sign=%d \n", val.size, val.E, val.sign);
- printArrayResult(val.digits, val.size);
- }
- int compare(int *a, int *b, int size)
- {
- for (int i = 0; i < size; i++)
- {
- if (a[i] > b[i])
- {
- return 1;
- }
- else if (b[i] > a[i])
- {
- return -1;
- }
- }
- return 0;
- }
- void minus(int array1[], int array2[], int size, int returnArray[])
- {
- for (int i = size - 1; i >= 0; i--)
- {
- if (array1[i] < array2[i])
- {
- array1[i] += 10;
- array1[i - 1] -= 1;
- }
- int res = array1[i] - array2[i];
- returnArray[i] = res;
- }
- }
- void incrementResult(int resultArray[], int index)
- {
- resultArray[index]++;
- if (resultArray[index] >= 10)
- {
- incrementResult(resultArray, index - 1);
- resultArray[index] -= 10;
- }
- }
- void shiftRight(int array[], int size, int shift)
- {
- for (int i = size - 1; i >= 0; i--)
- {
- int offset = i - shift;
- if (offset < size && offset >= 0)
- {
- array[i] = array[offset];
- }
- else
- {
- array[i] = 0;
- }
- }
- }
- void shiftLeft(int array[], int size, int shift)
- {
- for (int i = 0; i < size; i++)
- {
- int offset = i + shift;
- if (offset < size && offset >= 0)
- {
- array[i] = array[offset];
- }
- else
- {
- array[i] = 0;
- }
- }
- }
- int divide(int array1[], int array2[], int size, int returnArray[])
- {
- int shiftsAmount = 0;
- int compareResult = 0;
- do
- {
- compareResult = compare(array1, array2, size);
- if (compareResult < 0)
- {
- shiftRight(array2, size, 1);
- shiftLeft(returnArray, size, 1);
- shiftsAmount++;
- continue;
- }
- if (returnArray[0] != 0)
- {
- return shiftsAmount * -1;
- }
- incrementResult(returnArray, size - 1);
- minus(array1, array2, size, array1);
- }
- while (compareResult != 0);
- return shiftsAmount * -1;
- }
- struct BigDecimal normalize(struct BigDecimal decimal)
- {
- struct BigDecimal res = {.sign = decimal.sign, .size = DIGITS_SIZE};
- int e = decimal.E;
- for (int i = 0; i < res.size; i++)
- {
- if (i < decimal.size)
- {
- res.digits[i] = decimal.digits[i];
- }
- else
- {
- res.digits[i] = 0;
- e--;
- }
- }
- res.E = e;
- return res;
- }
- struct BigDecimal denormalize(struct BigDecimal decimal)
- {
- int leftZero = 0;
- int rightZero = 0;
- for (int i = 0; i < decimal.size; i++)
- {
- if (decimal.digits[i] == 0)
- {
- leftZero++;
- }
- else
- {
- break;
- }
- }
- for (int i = decimal.size - 1; i >= 0; i--)
- {
- if (decimal.digits[i] == 0)
- {
- rightZero++;
- }
- else
- {
- break;
- }
- }
- struct BigDecimal res = {
- .size = decimal.size - (leftZero + rightZero),
- .sign = decimal.sign,
- .E = decimal.E + rightZero
- };
- for (int j = leftZero; j < decimal.size - rightZero; ++j)
- {
- res.digits[j - leftZero] = decimal.digits[j];
- }
- return res;
- }
- struct BigDecimal floatingDivide(struct BigDecimal val1, struct BigDecimal val2)
- {
- struct BigDecimal result = {
- .sign = val1.sign * val2.sign,/*Определение знака результата*/
- /*Зануление массива цифр результата для исключения попадания мусора*/
- .size = DIGITS_SIZE,
- .digits = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
- };
- /*Привод к нормализованному виду первого и второго числа*/
- struct BigDecimal normVal1 = normalize(val1);
- struct BigDecimal normVal2 = normalize(val2);
- int e = 0;
- e = divide(normVal1.digits, normVal2.digits, DIGITS_SIZE, result.digits);
- result.E = normVal1.E - normVal2.E + e;
- struct BigDecimal denormResult = denormalize(result);
- return denormResult;
- }
- /*Функция, убирающая нули сразу после точки*/
- void remove_zero(int *digits, int *size, int *E)
- {
- int i = 0;
- int size_remember = *size;
- /*Если встретился 0 в начале массива цифр, то смещаем его в конец*/
- /*С последующем уменьшением размера массива цифр*/
- while (digits[i] == 0)
- {
- for (int j = 0; j < (size_remember - 1); j++)
- {
- swap(&digits[j], &digits[j + 1]);
- }
- --*size;
- }
- }
- void number_split(char *string, int *digits, int *size, int *E, int *sign)
- {
- /*Переменная для исключения добавления лишнего нуля в массив цифр*/
- int useless_zero = FALSE;
- if (string[1] == '0' && (string[0] == '-' || string[0] == '+') && (string[2] == '.'))
- {
- useless_zero = TRUE;
- }
- /*Переменная для отрезания незначащих нулей в конце*/
- /*для исключения их добавления в массив цифр*/
- int size_to_delete = 0;
- int index = 0;
- /*Проверка знака перед числом*/
- if (string[0] == '-')
- {
- *sign = NEGATIVE_NUMBER;
- }
- else
- {
- *sign = POSITIVE_NUMBER;
- }
- int E_flag = FALSE;/*Переменная для проверки наличия Е в числе*/
- int sign_E = POSITIVE_NUMBER;/*Знак порядка*/
- /*Переменная запоминающая старый порядок перед нормализацией*/
- int old_E = 0;
- int point_flag = FALSE;/*Переменная для проверки наличия точки в числе*/
- /*Проверка наличия целой части*/
- while (index < strlen(string))
- {
- /*Встретилась ли точка при записи числа*/
- if (string[index] == '.')
- {
- point_flag = TRUE;
- }
- /*Встретилась ли E при записи числа*/
- if (string[index] == 'E')
- {
- if (string[index + 1] == '-')
- {
- sign_E = NEGATIVE_NUMBER;
- }
- E_flag = TRUE;
- int index_zero_check = index;
- /*Удаление незначащих нулей с конца*/
- while (string[index_zero_check - 1] == '0')
- {
- index_zero_check--;
- ++(*E);
- size_to_delete++;
- }
- }
- /*Проверка на наличие целой части числа*/
- if ((string[index] != '+') && (string[index] != '-') && (string[index] != '.') &&
- (string[index] != 'E') && (E_flag == FALSE))
- {
- /*Встретилась ли точка?Т.к. целой части нет, то порядок далее убывает*/
- if (point_flag == TRUE)
- {
- --(*E);
- }
- /*Перевод чисел из char в int*/
- digits[*size] = string[index] - '0';
- ++(*size);
- }
- /*Запись изначального порядка числа*/
- if (E_flag == TRUE)
- {
- if ((string[index] != 'E') && (string[index] != '+') && (string[index] != '-'))
- {
- /*Запись старого порядка числа*/
- old_E = old_E + (string[index] - '0');
- if (strlen(string) > index + 1)
- {
- old_E = old_E * 10;
- }
- }
- }
- index++;
- }
- /*Корректировка размера массива цифр в соотв с наличием незначащих нулей*/
- *size = *size - size_to_delete;
- /*Смещение цифр в зависимости от наличия незначащего нуля в начале*/
- if (useless_zero == TRUE)
- {
- for (int j = 0; j < (*size - 1); j++)
- {
- swap(&digits[j], &digits[j + 1]);
- }
- --(*size);
- }
- /*Преобразование порядка с учетом знака Е*/
- old_E *= sign_E;
- /*Получение финального порядка числа*/
- *E = *E + old_E;
- remove_zero(digits, size, E);
- }
- char input_format_check(char *string)
- {
- /*Массив допустимых символов*/
- char allowed_array[14] = "0123456789E+-.";
- int size = 0;
- int E_quantity_check = 0; /*Подсчет кол-ва встречаемого символа E*/
- int sign_quantity_check = 0;/*Подсчет кол-ва встречаемого символа знака*/
- int dot_quantity_check = 0;/*Подсчет кол-ва встречаемого символа точки*/
- /*Если число не начинается со знака,то ошибка*/
- if ((string[size] != '-') && (string[size] != '+'))
- {
- return ERROR_CODE;
- }
- /*Движение по строке до ее конца*/
- while (size != strlen(string))
- {
- /*Переменная для проверки корректности введенного сивола*/
- int check_correct_input = 0;
- for (int i = 0; i < 14; i++)
- {
- /*Входит ли введенный символ в список допустиых*/
- if (string[size] == allowed_array[i])
- {
- check_correct_input = 1;
- }
- }
- if (string[size] == 'E')
- {
- /*Проверка обязательного знака после E*/
- if ((string[size + 1] != '-') && (string[size + 1] != '+'))
- {
- /*Проверка введен ли порядок после E*/
- if ((string[size + 2] != '0') && (string[size + 2] != '1')
- && (string[size + 2] != '2') && (string[size + 2] != '3')
- && (string[size + 2] != '4') && (string[size + 2] != '5')
- && (string[size + 2] != '6') && (string[size + 2] != '7')
- && (string[size + 2] != '8') && (string[size + 2] != '9'))
- {
- return ERROR_CODE;
- }
- }
- E_quantity_check++;
- }
- if (string[size] == '-' || string[size] == '+')
- {
- /*Проверка знака на первой позиции*/
- if ((size != 0))
- {
- /*Проверка знака после E*/
- if (string[size - 1] != 'E')
- {
- return ERROR_CODE;
- }
- }
- if (string[size + 1] == 'E')
- {
- return ERROR_CODE;
- }
- sign_quantity_check++;
- }
- if (string[size] == '.')
- {
- /*Исключение чисел с запятой в порядке*/
- if (E_quantity_check == DEGREE_LIMIT)
- {
- return ERROR_CODE;
- }
- dot_quantity_check++;
- }
- /*Проверка допустимого количества элементов*/
- if ((check_correct_input != 1) || (sign_quantity_check > SIGN_QUANTITY_LIMIT) \
- || (E_quantity_check > DEGREE_LIMIT) || (dot_quantity_check > DOT_LIMIT))
- {
- return ERROR_CODE;
- }
- /*Переход к следующему символу строки*/
- size++;
- }
- return RIGHT;
- }
- int input_function(char *input)
- {
- if (scanf("%100s", input) != INPUT_OK)
- {
- return ERROR_CODE;
- }
- /*Проверка длинны введенного чилса*/
- if (strlen(input) > ALLOWED_INPUT_SIZE)
- {
- printf("Input size exceeded");
- return ERROR_CODE;
- }
- /*Проверка корректности введенного формата числа*/
- if (input_format_check(input) != RIGHT)
- {
- printf("Invalid input format");
- return ERROR_CODE;
- }
- return RIGHT;
- }
- int main()
- {
- /*Правила ввода текста в консоли*/
- welcome_text();
- char input[ALLOWED_INPUT_SIZE];/*Строка ввода первого числа*/
- char input2[ALLOWED_INPUT_SIZE];/*Строка второго числа*/
- printf("Input first number:");
- /*Проверка правильного формата первого числа*/
- if (input_function(input) == ERROR_CODE)
- {
- return ERROR_CODE;
- }
- printf("\n");
- printf(" 1 15 30\n"
- " |-------------|--------------|\n");
- printf("Input second number:");
- /*Проверка правильного формата второго числа*/
- if (input_function(input2) == ERROR_CODE)
- {
- return ERROR_CODE;
- }
- /* Переменные для нормализации вида числа*/
- int digits[ALLOWED_INPUT_SIZE]; /* Массив цифр первого числа */
- int sign = 1;/*Знак первого числа*/
- int size = 0;/*Размер массива цифр первого числа*/
- int E = 0; /*Порядок первого числа*/
- int digits2[ALLOWED_INPUT_SIZE];/* Массив цифр второго числа */
- int sign2 = 1;/*Знак второго числа*/
- int size2 = 0;/*Размер массива цифр второго числа*/
- int E2 = 0;/*Порядок второго числа*/
- number_split(input, digits, &size, &E, &sign);/*Нормализация первого числа*/
- for (int i = 0; i < size; i++)
- {
- printf("%d ", digits[i]);
- }
- printf("sign = %d, E = %d , size = %d \n", sign, E, size);
- number_split(input2, digits2, &size2, &E2, &sign2);/*Нормализация второго числа*/
- for (int i = 0; i < size2; i++)
- {
- printf("%d ", digits2[i]);
- }
- printf("sign = %d, E = %d , size = %d \n", sign2, E2, size2);
- struct BigDecimal number1;/*Cтруктура первого числа*/
- struct BigDecimal number2;/*Структура второго числа*/
- number1.sign = sign;/*Добавление в структуру знака числа*/
- number1.E = E;/*Добавление в структуру порядка числа*/
- number1.size = size;/*Добавление в структуру размера числа*/
- /*Добавление в структуру массива цифр числа*/
- for (int i = 0; i < size; i++)
- {
- number1.digits[i] = digits[i];
- }
- number2.sign = sign2;/*Добавление в структуру знака числа*/
- number2.E = E2;/*Добавление в структуру порядка числа*/
- number2.size = size2;/*Добавление в структуру размера числа*/
- /*Добавление в структуру массива цифр числа*/
- for (int i = 0; i < size2; i++)
- {
- number2.digits[i] = digits2[i];
- }
- /*Создание структуры для результата*/
- struct BigDecimal result = floatingDivide(number1, number2);
- /*Вывод результата*/
- printBigDecimal(result);
- return RIGHT;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement