如何在C编程中使用递归来反转整数的顺序?

问题描述

问题陈述:

给出一个32位带符号整数,整数的倒数。

注意:假设我们正在处理一个只能存储的环境 32位有符号整数范围内的整数:[−2 ^ 31,2 ^ 31 − 1]。对于 为此问题的目的,假定您的函数在以下情况下返回0 反向整数溢出。

我正在尝试实现递归函数reverseRec(),它适用于较小的值,但是对于边缘情况却一团糟。

int reverseRec(int x)
{
    if(abs(x)<=9)
    {
        return x;
    }
    else
    {
        return reverseRec(x/10) + ((x%10)*(pow(10,(floor(log10(abs(x)))))));
    }
}

我已经实现了非递归函数,该函数工作得很好:

int reverse(int x)
{
    long long val = 0;
    do{
        val = val*10 + (x%10);
        x /= 10;
    }while(x);

    return (val < INT_MIN || val > INT_MAX) ? 0 : val;
}

在这里,我使用long long类型的变量 val 来检查带符号int类型的 MAX MIN 的结果,但是问题特别提到我们需要在32位整数范围内进行处理,尽管以某种方式被接受,但我只是好奇是否有一种方法可以仅使用int数据类型来实现递归函数

还有一件事情,即使我考虑使用long long,也无法在递归函数reverseRec()中实现它。

解决方法

是否有一种方法可以仅使用int数据类型来实现递归函数?
(和)在取反的整数溢出时返回0

是的

对于此类+/-问题,我喜欢将int值折叠到一侧并根据需要取反。折叠到一侧(-或+)可简化溢出检测,因为只有一侧需要测试

我宁愿折叠到负数一面,因为负数比正数多。 (使用32位int,对于此问题确实没有任何影响。)

由于代码形成了相反的值,因此请测试以下r * 10 + least_digit是否可能溢出。


int的递归解决方案,用于反转int。溢出返回0。

#include <limits.h>
#include <stdio.h>

static int reverse_recurse(int i,int r) {
  if (i) {
    int least_digit = i % 10;
    if (r <= INT_MIN / 10 && (r < INT_MIN / 10 || least_digit < INT_MIN % 10)) {
      return 1; /// Overflow indication
    }
    r = reverse_recurse(i / 10,r * 10 + least_digit);
  }
  return r;
}

// Reverse an int,overflow returns 0
int reverse_int(int i) {
  // Proceed with negative values,they have more range than + side
  int r = reverse_recurse(i > 0 ? -i : i,0);
  if (r > 0) {
    return 0;
  }
  if (i > 0) {
    if (r < -INT_MAX) {
      return 0;
    }
    r = -r;
  }
  return r;
}

测试

int main(void) {
  int t[] = {0,1,42,1234567890,1234567892,INT_MAX,INT_MIN};
  for (unsigned i = 0; i < sizeof t / sizeof t[0]; i++) {
    printf("%11d %11d\n",t[i],reverse_int(t[i]));
    if (t[i] != INT_MIN) {
      printf("%11d %11d\n",-t[i],reverse_int(-t[i]));
    }
  }
}

输出

          0           0
          0           0
          1           1
         -1          -1
         42          24
        -42         -24
 1234567890   987654321
-1234567890  -987654321
 1234567892           0
-1234567892           0
 2147483647           0
-2147483647           0
-2147483648           0
,

您可以添加第二个参数:

int reverseRec(int x,int reversed)
{
    if(x == 0)
    {
        return reversed;
    }
    else
    {
        return reverseRec(x/10,reversed * 10 + x%10);
    }
}

并调用传递第二个参数0的函数。如果需要负数,可以先检查符号,然后将绝对值传递给该函数。

,

在尝试学习C编程时,我编写了这个问题,并得到了一些正确的结果和一些不正确的结果。我看不出差异的原因。

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>  // requires adding link to math -lm as in: gcc b.c -lm -o q11

    int ReverseInt(int startValue,int decimalPlace)
    {
        if(decimalPlace == 0)  // if done returns value
        {
            return startValue;
        }
    int temp = startValue % 10;  // gets units digit
    int newStart = (startValue -temp)/10; // computes new starting value after removing one digit
    int newDecimal = decimalPlace -1;
    
    
    int value = temp*pow(10,decimalPlace);
    return value + ReverseInt(newStart,newDecimal);  // calls itself recursively until done
    }


    int main()
    {
        int x,decimalP,startValue;
        printf("Input number to be reversed \n Please note number must be less than 214748364 :");
        scanf("%d",&x);
        if (x > 214748364)
        {
            printf("Input number to be reversed \n Please note number must be less than 214748364 :");
            scanf("%d",&x);
        }
        decimalP = round(log10(x));  // computes the number of powers of 10 -  0 being units etc.
        startValue = ReverseInt(x,decimalP);  // calls function with number to be reversed and powers of 10
        printf("\n reverse of %d is %d \n",x,startValue);
    }

输出为:1234的倒数是4321,然后4321的倒数是12340

,

我假设通过反转整数来表示将129转换为921或将120转换为21。

您需要一个初始方法来初始化您的递归函数。 您的递归函数必须计算出整数使用的小数位数。可以使用以10为底的对数值,然后将结果转换为整数来找到它。

    大约
  • log10(103) 2.04 => 2

将初始值乘以10以得到该位置并将其存储在名为temp的变量中 从初始值中减去该位置,并将其存储在名为newStart的变量中。

  • 将该值除以10

从小数点后一位减去并存储在另一个名为newDecimal的变量中。

将乘数乘以10到小数点的幂,然后将其添加到初始值为newStart而小数位为newDecimal的函数中。

#include <stdio.h>
#include <math.h>

int ReverseInt(int startValue,int decimalPlace);

int main()
{
    int i = -54;
    int positive = i < 0? i*-1 : i;
    double d = log10(positive);
    int output = ReverseInt(positive,(int)d);
    int correctedOutput = i < 0? output*-1 : output;
    printf("%d \n",correctedOutput);
    return 0;
}

int ReverseInt(int startValue,int decimalPlace)
{
    if(decimalPlace == 0)
    {
        return startValue;
    }
    int temp = startValue % 10;
    int newStart = (startValue -temp)/10;
    int newDecimal = decimalPlace -1;
    
    
    int value = temp*pow(10,newDecimal);
}
,

已经很晚了,没有比我更好的事情了。没有浮点计算。当然,整数必须足够大以容纳结果。否则是UB。

int rev(int x,int partial,int *max)
{
    int result;
    if(x / partial < 10 && (int)(x / partial) > -10)
    {
        *max = partial;
        return abs(x % 10) * partial;
    }
    result = rev(x,partial * 10,max) + abs(((x / (int)(*max / partial)) % 10) * partial);
    return result;
}

int reverse(int x)
{
    int max;
    return rev(x,&max) * ((x < 0) ? -1 : 1);
}


int main(void){
  
  printf("%d",reverse(-456789));
}

https://godbolt.org/z/M1eezf

unsigned rev(unsigned x,unsigned partial,unsigned *max)
{
    unsigned result;
    if(x / partial < 10)
    {
        *max = partial;
        return (x % 10) * partial;
    }
    result = rev(x,max) + (x / (*max / partial) % 10) * partial;
    return result;
}

unsigned reverse(unsigned x)
{
    unsigned max;
    return rev(x,&max);
}


int main(void){
  
  printf("%u",reverse(123456));
}

当使用long long存储结果时,所有可能的整数都可以反转

long long rev(int x,long long partial,long long *max)
{
    long long result;
    if(x / partial < 10 && (int)(x / partial) > -10)
    {
        *max = partial;
        return abs(x % 10) * partial;
    }
    result = rev(x,max) + abs(((x / (int)(*max / partial)) % 10) * partial);
    return result;
}

long long reverse(int x)
{
    long long max;
    return rev(x,&max) * ((x < 0) ? -1 : 1);
}


int main(void){
  
  printf("%d reversed %lld\n",INT_MIN,reverse(INT_MIN));
  printf("%d reversed %lld\n",reverse(INT_MAX));
}

https://godbolt.org/z/KMfbxz