繁体   English   中英

添加32位登录C

[英]Adding 32 bit signed in C

我已经得到了这个问题,并想用C解决它:

假设您有一个32位处理器,并且C编译器不支持long long(或long int)。 编写一个函数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位寄存器实现long类型,以便我可以正确打印该值。 有人可以帮助我如何使用下溢和上溢信息,以便我可以将结果正确存储在c变量中,我认为应该是2个32位位置。 我认为问题所在就是暗示不支持该长度。 变量c是否将2个32位寄存器组合在一起以保持正确的结果以便可以打印? 当结果过大或过少时,我应该执行什么操作?

由于这是一个家庭作业问题,因此我将尽量避免完全破坏它。

这里一个令人讨厌的方面是,结果比您所允许使用的任何结果都要大(我解释说禁止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的低位数字是3? 仅给出7、6和3,如何确定结果的第二位? 您应该也可以将所有这些都应用到以2为基数的32上

首先,满足上述要求的最简单解决方案:

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;
}

最难的部分是对结果进行一些有用的操作,例如打印结果。 正如harold所建议的那样,打印功能不需要进行完全除法,它可以简单地覆盖可能的大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);
}

剩下的工作是将其转换为带符号的数量。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM