C 中的大数减法

发布于 2024-08-02 13:00:54 字数 1179 浏览 8 评论 0原文

大约 20 分钟前,我刚刚完成了 C 入门课程的考试。考试的第一题让我有些措手不及,涉及找出两个大数的差异。

目标是按值获取两个结构(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 的内部工作原理即可。

为了以防万一,不要使用按位运算符。

I just finished my exam in an introductory C course about 20 minutes ago. The first question on the exam caught me somewhat off guard, and involved finding the difference two large numbers.

The goal was to take two structures (N1 and N2) by value, and store the difference in a structure passed by reference (N3). We were allowed to assume N3 was initiated with all '0's. The MAX size can be anything, so the solution still has to work if the numbers are over 100 digits.

Here's the base code (original may be slightly different, this is from memory)

#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' }
*/

The problem isn't so much in finding a solution to this problem, but that only about ~20 lines were provided for the complete answer. My method for solving involved subtracting the digits one at a time after converting to integers, and then making appropriate carries if the result was negative. This took substantially more space than what was provided.

Based on the small amount of marks and the space provided for this question, I'm lead to believe that there's a fairly trivial solution that I'm not seeing. What is it? I have now finished the course but this question is still bothering me!

A complete solution isn't required, just the inner workings of the function difference.

No bitwise operators are to be used, just in case.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

瑶笙 2024-08-09 13:00:54

大多数计算机科学课程中的 BigNumber 问题旨在让您必须精确地按照您所描述的方式“手动”进行算术:将每个字符转换为整数,进行减法,并在适当的情况下借位。

正如您所描述的那样,您的计划攻击应该只有几行。在伪代码中,像这样:(

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;

加上将相同的逻辑也应用于十进制数字的一些额外麻烦。)

听起来你有正确的想法,也许只是过度考虑了实现?

The BigNumber problem in most Computer Science classes is designed to make you have to do the arithmetic "by hand" precisely as you describe: convert each character to an integer, subtract, and borrow where appropriate.

Your plan attack, just as you've described it, should be only a few lines. In pseudocode, something like this:

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;

(Plus a little extra hassle to apply the same logic to the decimal digits too.)

It sounds like you had the right idea, and perhaps just over-thought the implementation?

影子是时光的心 2024-08-09 13:00:54

如果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);
    }
}

This should work if N1 >= N2. This also assumes that the arrays are laid out like 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);
    }
}
如梦初醒的夏天 2024-08-09 13:00:54

亲爱的教授,减法应该用加法来定义。我已经重载了一元“-”运算符并在其他地方定义了 bignum 加法例程。我正在使用 9 的补码 来简化/加速加法(不需要讨厌的进位!)使用基于表格的答案查找(当只有 10 个答案时为什么要计算总和?)。 bigNum 减法例程(根据您的规格)如下:

void bigDifference(bigNum N1, bigNum N2, bigNum *N3) {
    bigSum(N1, -N2, N3);
}

Dear professor, subtraction should be defined in terms of addition. I've overloaded the unary "-" operator and defined the bignum addition routine elsewhere. I'm using 9's complement to simplify/speed up the addition (no pesky carry required!) with a table based answer lookup (why calculate the sums when there are only 10 of them?). The bigNum subtraction routine (to your specs) follows:

void bigDifference(bigNum N1, bigNum N2, bigNum *N3) {
    bigSum(N1, -N2, N3);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文