Вычитание больших чисел в C

Я только что закончил свой экзамен во вводном курсе C около 20 минут назад. Первый вопрос на экзамене заставил меня отвлечься от страха и потребовал найти разницу в двух больших числах.

Цель состояла в том, чтобы взять две структуры (N1 и N2) по значению и сохранить разницу в структуре, переданной ссылкой (N3). Нам разрешили предположить, что N3 был начат со всех "0". Размер MAX может быть любым, поэтому решение по-прежнему должно работать, если цифры более 100 цифр.

Здесь базовый код (оригинал может быть немного другим, это из памяти)

#include <stdio.h>
#include <stdlib.h>
/* MAX can be any length, 10, 50, 100, etc */
#define MAX 10

struct bignum
{
    char digit[MAX];
    char decimaldigit[MAX/2];
};
typedef struct bignum bigNum;
void difference(bigNum, bigNum, bigNum *);

/*
    Original values in N1 and N2

    N1.digit = { '0', '0', '0', '5', '4', '8', '2', '0', '9', '0'};
    N1.decimaldigit { '0', '0', '0', '4', '9' };

    N2.digit = { '0', '0', '0', '4', '8', '1', '3', '1', '4', '5'};
    N2.decimaldigit { '8', '0', '1', '2', '0' };
*/

/*
    Result would be:
    N3.digit = { '0', '0', '0', '0', '6', '6', '8', '9', '4', '4'}
    N3.decimaldigit { '1', '9', '9', '2', '9' }
*/

Проблема заключается не столько в поиске решения этой проблемы, сколько в том, что для полного ответа было предоставлено всего около 20 строк. Мой метод решения включает в себя вычитание цифр по одному после преобразования в целые числа, а затем создание соответствующих переносов, если результат был отрицательным. Это заняло значительно больше места, чем предусмотрено.

Основываясь на небольшом количестве меток и пространстве, предоставленных для этого вопроса, я убежден, что существует довольно тривиальное решение, которое я не вижу. Что это? Я закончил курс, но этот вопрос по-прежнему беспокоит меня!

Полное решение не требуется, только внутренняя работа функции difference.

На всякий случай нельзя использовать побитовые операторы.

4
22 авг. '09 в 23:17
источник поделиться
4 ответов

Это должно работать, если N1 >= N2. Это также предполагает, что массивы выложены как dn...d2d1d0.e0e1...em.

char digchr(int); // Converts a single-digit integer into a character.

void difference(bigNum N1, bigNum N2, bigNum *N3) {
    int carry = 0;

    for (int i = MAX / 2 - 1; i >= 0; i--) {
        int diff = N1.decimalDigits[i] - N2.decimalDigits[i] - carry;
        if (diff < 0) { 
            diff += 10;
            carry = 1;
        } else {
            carry = 0;
        }

        N3->decimalDigits[i] = digchr(diff);
    }

    for (int i = 0; i < MAX; i++) {
        int diff = N1.digits[i] - N2.digits[i] - carry;
        if (diff < 0) {
           diff += 10;
           carry = 1;
        } else {
            carry = 0;
        }

        N3->digits[i] = digchr(diff);
    }
}
4
22 авг. '09 в 23:28
источник

Проблема BigNumber в большинстве классов Computer Science предназначена для того, чтобы заставить вас делать арифметику "вручную" точно так же, как вы описываете: конвертировать каждый символ в целое число, вычитать и брать там, где это необходимо.

Ваша атака плана, как вы ее описали, должна быть всего лишь несколькими строками. В псевдокоде что-то вроде этого:

for each character (right to left):
    difference = N1.digit[i] - N2.digit[i];
    if (difference < 0)
        N1.digit[i - 1]--;
        difference += 10;
    N3.digit[i] = difference;

(Плюс немного дополнительных хлопот, чтобы применить одну и ту же логику к десятичным цифрам тоже.)

Похоже, у вас была правильная идея и, возможно, просто передумала реализация?

9
22 авг. '09 в 23:27
источник

Уважаемый профессор, вычитание должно быть определено с точки зрения добавления. Я перегрузил унарный оператор "-" и определил процедуру добавления бинума в другом месте. Я использую 9 дополнение, чтобы упростить/ускорить добавление (не надоедливый перенос требуется!) С поиском ответов на основе таблицы (зачем вычислять суммы, когда их всего 10?). Процедура вычитания bigNum (к вашим спецификациям) следует:

void bigDifference(bigNum N1, bigNum N2, bigNum *N3) {
    bigSum(N1, -N2, N3);
}
2
24 авг. '09 в 23:47
источник

Я пробовал найти простые ответы, но это самый простой, о котором я мог подумать. Конечно, всегда предполагайте, что вход 1 больше, чем вход 2... И пользователь должен вводить в виде то есть (1000-0001), а скорее чем (1000-1). если у кого-то есть решение. Пожалуйста, дайте мне знать.

void subtraction(char input1[16],char input2[16])
{
int i1len = strlen(input1);
int i2len = strlen(input2);
int i,j,k = 0;
int id=0;

int result[16];
i=(i1len -1);
j=(i2len - 1);

while(i>=0 && j>=0)
{
    result[k]=((input1[i]-'0')-(input2[j]-'0'));
    if(result[k]<0)
    {
        id=i;//to store the current value of the array
        while (input1[id--]==0)
        {
            input1[id]=9;
            id--;//going to the next number on the left of the array..
        }
        input1[id]--;//decrementing by 1 since we are borrowing from that 
number
        result[k]=((input1[i]-'0')-(input2[j]-'0')+10);//here we are adding an 
extra 10 since we have just borrowed it..
    }
    k++;
    i--;
    j--;
}
k--;
while(result[k]==0 && k!=0)//to remove the trailing zeros..
k--;
for(;k>=0;k--)
{
 printf("%d",result[k]);
}
getchar();

}
0
06 дек. '18 в 19:53
источник

Посмотрите другие вопросы по меткам или Задайте вопрос