2015-09-19 24 views
-1

签署我一直在考虑这个问题,想解决它在C:添加32位用C

假设你有一个32位处理器和C编译器不支持长很长(或长整型)。写一个函数add(a,b),它返回c = a + b,其中a和b是32位整数。

我写了这个代码能够检测溢和下溢

#define INT_MIN  (-2147483647 - 1) /* minimum (signed) int value */ 
#define INT_MAX  2147483647 /* maximum (signed) int value */ 

int add(int a, int b) 
{ 

    if (a > 0 && b > INT_MAX - a) 
    { 
     /* handle overflow */ 
     printf("Handle over flow\n"); 
    } 
    else if (a < 0 && b < INT_MIN - a) 
    { 
     /* handle underflow */ 
     printf("Handle under flow\n"); 
    } 
    return a + b; 
} 

我不知道如何实现长期使用32个寄存器,这样我可以正常打印的价值。有人可以帮助我如何使用下溢和溢出信息,以便我可以将结果正确地存储在c变量中,我认为应该是2个32位位置。我想这就是问题所在,当它暗示那么长时间不被支持时。变量c是否将2 32位寄存器放在一起以保持正确的结果,以便可以打印?当结果过度或不足时,我应该做什么样的行动?

+1

请注意您的问题在写入时的样子。将代码标记为代码,使其看起来合理。我现在已经修复了它,但请注意它。 –

+0

你所要求的一切都完全是特定于实现的。 –

+2

'INT_MAX'宏已经存在于'limits.h'中,你自己不需要这样做。只需包含标题。 – ameyCU

回答

0

首先,满足问题,说最简单的办法:

double add(int a, int b) 
{ 
    // this will not lose precision, as a double-precision float 
    // will have more than 33 bits in the mantissa 
    return (double) a + b; 
} 

更严重的是,这位教授可能预期的数字分解成整数的组合。保持两个32位整数的和需要33位,可以用一个int和一个位来表示进位标志。假设无符号整数为简单起见,将添加这样来实现:

struct add_result { 
    unsigned int sum; 
    unsigned int carry:1; 
}; 

struct add_result add(unsigned int a, unsigned int b) 
{ 
    struct add_result ret; 
    ret.sum = a + b; 
    ret.carry = b > UINT_MAX - a; 
    return ret; 
} 

较难的部分是做一些其结果是有用的,诸如打印。正如哈罗德所提议的那样,打印功能不需要进行完全的分割,它可以简单地覆盖可能的大的33位值并对这些范围的第一位进行硬编码。下面是一个实现,同样限于无符号整数:

void print_result(struct add_result n) 
{ 
    if (!n.carry) { 
    // no carry flag - just print the number 
    printf("%d\n", n.sum); 
    return; 
    } 
    if (n.sum < 705032704u) 
    printf("4%09u\n", n.sum + 294967296u); 
    else if (n.sum < 1705032704u) 
    printf("5%09u\n", n.sum - 705032704u); 
    else if (n.sum < 2705032704u) 
    printf("6%09u\n", n.sum - 1705032704u); 
    else if (n.sum < 3705032704u) 
    printf("7%09u\n", n.sum - 2705032704u); 
    else 
    printf("8%09u\n", n.sum - 3705032704u); 
} 

将其转换为带符号数量将留作练习。

+0

我真的不认为教授想让我使用浮点。我真的不认为这是问题所在。我很欣赏这种回应是一种诚实的尝试。 – DonRobb

+0

我看到幽默感,并且在里面发痒,但我不知道我的教授是否会像我们一样看到幽默感? – DonRobb

+0

我猜测一些DV可能是由于错误的评估 - 由于双重属性 - 存在一些精度问题。没有,在这里。 –

2

由于这是一个家庭作业问题,我会尽量不要完全破坏它。

这里一个令人讨厌的方面是,结果比任何你允许使用的都大(我解释的禁令long long也包括int64_t,否则就没有意义了)。对结果值进行“两个整数”可能是一种尝试,但对于解释这个值的奇怪。所以我会选择两个uint32_t,并将它们解释为64位二进制补码整数的两半。

无符号多字加法很简单,并且已经被覆盖很多次(只是搜索)。签署的变种确实是相同的,如果输入是符号扩展:(未测试)

uint32_t a_l = a; 
uint32_t a_h = -(a_l >> 31); // sign-extend a 
uint32_t b_l = b; 
uint32_t b_h = -(b_l >> 31); // sign-extend b 
// todo: implement the addition 
return some struct containing c_l and c_h 

解释时签署的,显然它不能溢出64位的结果。它可以(有时应该)包装。

要打印这个东西,如果这是作业的一部分,请首先确定哪些值为c_h。没有太多的可能性。使用现有的整数打印功能打印应该很容易(也就是说,您不必编写整个多字 - itoa,只需处理几个案例)。

作为添加的提示:当您添加两位十进制数字并且结果大于9时会发生什么?为什么7 + 6 = 13 a 3的低位?只给出7,6和3,你如何确定结果的第二位数?您应该能够将所有这些应用于基础2 以及。

+0

请破坏它哈罗德。我认为这可能是最好的答案。我非常感谢你正确地看到问题 – DonRobb

+0

@DonRobb这很危险,你知道吗?如果你的老师发现这个问题怎么办?甚至没有那么难,你知道它已经在10号基础上工作了,唯一的区别是基地 – harold

+0

我认为它会好的。我以前做过这种类型的事情。我会以任何方式使用世界的工具,以便我理解。我确实认为我知道你在做什么,并且非常感谢你的帮助。我只需要添加并使用我认为是因为底座是2.我打算去玩你提供的东西。自从你是唯一一个获得它的人以后,我仍然很想看你是如何做到的。请请美观。 – DonRobb