【问题标题】:Adding and Subtracting Bigints Using Linked Lists使用链表添加和减去 Bigint
【发布时间】:2010-09-12 18:22:32
【问题描述】:

我几乎完成了这项任务,这让我很生气。这是我关于这三个不同部分的第三篇文章,老实说,我很尴尬,因为我正在为这项任务而苦苦挣扎。

任务本身是编写一个程序,使用链表执行大整数的加法和减法(我慢慢开始讨厌链表,在 Lisp 之外)。现在一切似乎都在工作,除了实际的加法和减法。我不确定它是否是算术函数,因为它们以前可以工作(但从来没有 100%),但与 S/O 社区核实并没有什么坏处(通常我不会要求这么多帮助完成一项任务,因为我更喜欢自己解决问题,但这是糟糕而忙碌的一周,而且截止日期快到了)。

我写的算术函数如下,谁能帮我找出问题所在?

/*
 * Function add
 *
 * @Paramater STRUCT* Integer
 * @Parameter STRUCT* Integer
 *
 * Takes two linked lists representing
 * big integers stored in reversed order,
 * and returns a linked list containing
 * the sum of the two integers.
 *
 * @Return STRUCT* Integer
 * 
 * TODO Comment me
 */
struct integer* add( struct integer *p, struct integer *q )
{
    int carry = 0;

    struct integer *sHead, *sCurr;
    struct integer *pHead, *qHead;

    pHead = p;
    qHead = q;

    sHead = NULL;

    while( p )
    {
        sCurr = ( struct integer* ) malloc (sizeof(struct integer));
        sCurr->digit = p->digit + q->digit + carry;
        sCurr->next = sHead;
        sHead = sCurr;

        carry = 0;

        /*
         * If the current digits sum to greater than 9,
         * create a carry value and replace the current
         * value with value mod 10.
         */
        if( sCurr->digit > 9 )
        {
            carry = 1;
            sCurr->digit = sCurr->digit % 10;
        }

        /*
         * If the most significant digits of the numbers
         * sum to 10 or greater, create an extra node
         * at the end of the sum list and assign it the
         * value of 1.
         */
        if( carry == 1 && sCurr->next == NULL )
        {
            struct integer *sCarry = ( struct integer* ) malloc (sizeof(struct integer));
            sCarry->digit = 1;
            sCarry->next = NULL;
            reverse( &sCurr );
            sCurr->next = sCarry;
            reverse( &sCurr );
        }

        p = p->next;
        if( q->next ) q = q->next; 
        else q->digit = 0; 
    }

    return sHead;
}

/*
 * Function subtract
 *
 * @Parameter STRUCT* Integer
 * @Parameter STRUCT* Integer
 *
 * Takes two linked lists representing struct integers.
 * Traverses through the lists, subtracting each
 * digits from the subsequent nodes to form a new
 * struct integer, and then returns the newly formed
 * linked list.
 *
 * @Return STRUCT* Integer
 * 
 * TODO Comment me
 */
struct integer* subtract( struct integer *p, struct integer *q )
{
    int borrow = 0;

    struct integer *dHead, *dCurr;
    struct integer *pHead, *qHead;

    pHead = p;
    qHead = q;

    dHead = NULL;

    while( p )
    {
        dCurr = (struct integer*) malloc (sizeof(struct integer));
        if( q )
        {
            dCurr->digit = p->digit - q->digit - borrow;
        }
        else
        {
            dCurr->digit = p->digit - borrow;
        }
        dCurr->next = dHead;

        if( dCurr->digit < 0 )
        {
            dCurr->digit += 10;
            borrow = 1;
        }

        dHead = dCurr;

        p = p->next;
        if( q->next) q = q->next;
    }

    return dHead;
}



示例输出应如下所示:
8888888888 + 2222222222 = 11111111110
10000000000 – 9999999999 = 1
10000000000 – 9999999999 = 1

但是,它看起来像这样:

8888888888 + 2222222222 = 1111111110
10000000000 - 9999999999 = 10000000001
10000000000 - 9999999999 = 10000000001

编辑整个程序(截至美国东部标准时间下午 3:30 的当前形式)可通过here 参考,或者在这些功能不是问题的情况下提供。

【问题讨论】:

  • 如何使用调试器并显示每个步骤发生了什么。似乎这不是关于链表本身,而是关于你如何减去。顺便说一句,最好在减法中将其命名为“借”而不是“进位”。
  • 特别感兴趣的是 dCurr->digit、p->digit、q->digit 的输出。而且您还没有显示整数类型是如何定义的。
  • @Pmod 对不起,我会把整个程序的粘贴箱作为参考。

标签: c linked-list


【解决方案1】:

else q-&gt;digit = 0;
您正在更改函数内部的参数。

尝试更改您的函数以接受const 参数并重新编译。

struct integer* add( const struct integer *p, const struct integer *q )
struct integer* subtract( const struct integer *p, const struct integer *q )

【讨论】:

  • 作为作业的一部分,我无法更改函数定义。 ://
  • 好的,但无论如何都要改变,用const编译直到没有错误,然后删除const :)
  • 事实证明,最大的问题是 else q-&gt;digit = 0 就其中一个不稳定的错误,感谢您指出这一点。
  • 感谢安德鲁的反馈。我就知道!哈哈!但我不想有太多“寻找虫子”的乐趣。这是你的错误,你应该得到乐趣:)
【解决方案2】:

读取的部分

if( dCurr->next == NULL && carry == 1 )
{
    struct integer *dCarry = (struct integer*) malloc (sizeof(struct integer));
    dCarry->digit = -1;
    dCarry->next = NULL;
    dCurr->next = dCarry;
}

看起来有点不对劲。从上面的代码中,dCurr-&gt;next 被设置为我们在之前的循环中已经计算过的数字,所以它只有第一个数字为 NULL。我想你的意思是检查p-&gt;next

我假设条件len(p) &gt;= len(q) 适用于此函数。如果没有,你将不得不做一些处理它不存在的地方(在你用完 q 个节点之前用完 p 个节点)。我还假设这些数字在列表中从最低有效数字到最高有效数字。如果没有,您可能需要在处理它们之前反转 p 和 q。

我不知道的另一件事是您如何处理负数。或者即使你应该处理它们。在这样的结构中添加并不容易,因为在减去时,在末尾添加一些东西的天真方法是行不通的:当 q 为负时,你会费尽心思从 p 中减去 q,然后发现你应该添加。

【讨论】:

  • 幸运的是,该程序只处理非负整数。另外,我确实设置了它,以便永远不会用p &lt; q 调用subtract()
【解决方案3】:

compare() 函数中,你“行走”p,然后尝试再次行走。

int compare( struct integer *p, struct integer *q )
{
    /* ... */
    while( p )
    {
        pCount++;
        p = p->next;
    }

p 现在为 NULL

    /* ... */
    while( p )
    {
        /* ... */
    }

while 循环永远不会运行。

【讨论】:

  • 很好的发现,谢谢。现在剩下的唯一问题是subtract() 函数。 :(
  • 如果要减去的数字的长度不同会怎样?假设12 - 8 ...该函数执行的第一个数字操作是什么?
  • 嗯,数字是反向存储的,所以应该是2 - 8 = -6,然后是-6 + 10 = 4
  • 嗯...我忘记了相反的事情。但是q12 - 8 中会发生什么? q-&gt;digit 是 8,q-&gt;next 是 NULL。注意while中的最后一条语句
  • @pmg 我把它改成了if( qCurr-&gt;next ) qCurr = qCurr-&gt;next; else qCurr-&gt;digit = 0;。我得到了非常奇怪的结果,pastebin.com/LqLdDSHH 证明了这一点
猜你喜欢
  • 2018-09-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-27
相关资源
最近更新 更多