递归函数,用于计算数字中的位数

时间:2018-01-20 14:53:16

标签: c++ recursion

有没有办法对递归函数进行编码,该函数打印数字中的数字位数,以便:

- 这是一项无效功能

-The" if"条件是if(num == 0),返回

-The" else"将调用递归。

我看到了两种不同类型的代码,其中一种是" if" condition有递归调用,else用于" return"。但这不是我想要的。

我对递归很不好,并试图通过自己编码来理解它,但没有成功。

这是我的代码(我理解为什么它打印122而不是3但是我真的不知道代码的不同之处。帮助任何人?)

    #include <iostream>
    #include <string.h>
    using namespace std;
    void numOfDigits(unsigned int num);

    int main(){
        int num = 994;
        numOfDigits(num);
    }
    void numOfDigits(unsigned int num)
    {
        int size = 1;
        if (num==0)
            return;
        else
        {
            if (num / 10 != 0)
                size++;
            numOfDigits(num / 10);
        }
        cout << size;
    }

10 个答案:

答案 0 :(得分:1)

使这段代码有效的快速入侵是让size变为静态,即更改

int size = 1;

static int size = 1;

但这只在您第一次调用该函数时才有效。

对于更强大的解决方案,在每次调用函数时,您必须传递计数到目前为止:

void numOfDigits(unsigned int num, int countSoFar = 0) {
    if (num == 0)
        std::cout << countSoFar << '\n';
    else
        numOfDigits(num / 10, countSoFar + 1);
}

答案 1 :(得分:1)

您可以通过引用传递值并使用它,每次调用此函数时初始化ans=0

void recursive(unsigned int num,int &ans){
    if(num == 0){
        return;
    }
    else{
        ans++;
        recursive(num/10,ans);
    }
}

请参阅thisthis

答案 2 :(得分:1)

你在numOfDigits()函数中有很多错误。

  1. 首先,每次调用函数时,都会声明一个名为size的新局部变量。这与&#39; size&#39;无关。在调用函数中定义。要看到这一点,请在初始化后打印尺寸。要解决此问题,请将尺寸设为静态;然后,每次调用函数时都会使用相同的静态变量。
  2. 当您在函数末尾打印大小时,它只是在运行该函数后给出大小变量的值。即使您将大小设置为静态,您也将打印大小的中间值。解决这个问题的一个简单方法是允许函数返回大小,你只需要在main函数中打印函数的值。

    #include <iostream>
    #include <string.h>
    using namespace std;
    int numOfDigits(unsigned int num);
    
    int main(){
            int num = 994;
            cout<<numOfDigits(num);
    }
    int numOfDigits(unsigned int num)
    {
            static int size = 1;
            if (num==0)
                return 0;
            else
            {
                if (num / 10 != 0)
                    size++;
                numOfDigits(num / 10);
            }
            return size ;
    }
    
  3. 确保根据需要放置(num == 0)的情况;在这种情况下,它打印0作为答案。

    PS:打印数字后总是放一个空格。否则你可能会认为1 2 2(实际打印的数字)是数字122。

答案 3 :(得分:0)

#include <iostream>
#include <string.h>
using namespace std;
void numOfDigits(unsigned int num);

void main(){
    int num = 994;
    int size = 1;
    cout << numOfDigits(num, size);
}
void numOfDigits(unsigned int num, int &size)
{

    if (num==0)
        cout<<size;
    else
    {
        if (num / 10 != 0)
            size++;
        numOfDigits(num / 10, size);
    }

}

答案 4 :(得分:0)

尝试全局声明大小,因为每次执行功能时它都是初始化的

   int size = 1;
void numOfDigits(unsigned int num)
    {

        if (num==0)
            return;
        else
        {
            if (num / 10 != 0)
                size++;
            numOfDigits(num / 10);
        }
    }

打印主要

内的大小值

答案 5 :(得分:0)

不使用任何全局变量,此代码有效。只需注意一点:你在参数中声明了unsigned int,但是你给函数的数字是有符号整数。

 #include <iostream>
    #include <string.h>
    using namespace std;
    void numOfDigits(unsigned int num, unsigned int& digits);

    int main(){
        unsigned int num = 93934;
        unsigned int digits = 1;
        numOfDigits(num, digits);
        cout <<digits <<endl;

        return 0;
    }

    void numOfDigits(unsigned int num, unsigned int& digits) {
        if (num==0){
            return;
        }else{
            if (num / 10 != 0){
                ++digits;
                numOfDigits(num / 10, digits);
            }
        }
    }

答案 6 :(得分:0)

我认为您的误解是您认为size一个单个变量。但是,在每次调用函数时,您都有不同的函数。此外,每次调用您的函数都会再次打印它。

你的主要cout什么也没做,因为它打印出一个没有内容的空白。

通常,你给它一个返回参数,就是累计数,比如

int numOfDigits(unsigned int num);
void main(){
    cout << numOfDigits(994) << endl;
}

如果您因某些原因不想这样做,可以参考:

int numOfDigits(unsigned int num, unsigned int& digits);
void main(){
    unsigned int digits;
    numOfDigits(994,digits);
    cout << digits << endl;
}

但那不是那么好。

那就是说,就风格而言,我要做的就是让它成为一个循环(想法是你想要避免递归大多数时间):

unsigned int numOfDigits(unsigned int num){
    if(num == 0) { return 1; }
    unsigned int size = 0;
    while(num != 0){
        size++;
        num /= 10;
    }
    return size;
}

也可以通过引用返回值调用来完成。但同样,如果没有必要,这有点奇怪。

你甚至可以使用数学cout << floor(log_10(num)) << endl;(如果num为零,不考虑特殊情况)将其作为单行代码。

一种解决方案也可以使尺寸成为全局变量。但是,我建议反对。一般应避免全局变量。如果有人推荐的话,只是想提一下。

最后,你可以使用一个类,如DigitsCounter,它通常是短暂的,并且对方法进行递归调用,其中size变量是类成员。不过,这在你的情况下是过度的。

答案 7 :(得分:0)

  • numOfDigits是一个无效函数

  • “if”条件为if(num == 0),返回

  • “else”将调用递归。

下面:

void numOfDigits(unsigned int num)  {
    if (num == 0)
        return;

    // The "else" will call the recursion.
    else {

        static int size = 1;

        if (num / 10 != 0) {
            size++;

            numOfDigits(num / 10);
        }

        else {
            cout << size << '\n';
            size = 1;
        }
    }
}

答案 8 :(得分:0)

试试这段代码:

int numOfDigits(unsigned int num)
{
    int size = 1;
    if (num!=0)
    {
        if (num / 10 != 0)
           size+= numOfDigits(num / 10);
    }
    return size;
}

使用主函数

中的返回值

答案 9 :(得分:0)

在递归函数上使用void返回类型的问题是,嵌套调用无法将任何信息返回给调用它们的方法。如果我们想在第一个(外部)呼叫时打印该值,则该第一个呼叫无法从其递归呼叫中获取任何信息。

正如您所观察到的那样,我们不可能只是按原样打印该值,因为从递归调用到输出字符的一对一映射(如果我们使用Base 10 ...参见附录)。如果我们放松if条件必须立即返回的条件,我们可以通过将信息作为参数传递给递归调用然后在递归的最深层打印值来避免这个问题。例如:

// The accumulator starts at 0, then increases by 1 for each recursive call
void numOfDigits(unsigned int num, unsigned int accumulator = 0) {
  if (num == 0) {
    if (accumulator == 0) cout << 1; // Special case: numOfDigits(0) = 1
    else cout << accumulator;

  } else numOfDigits(num / 10, accumulator + 1);
} 

旁注:这是一个尾递归方法:它将递归调用作为最后一个操作。这很有用,因为它允许编译器降低方法的空间复杂度(参见explanation)。本质上,编译器将方法转换为简单迭代,从而无需累积堆栈帧。

附录:我能看到保留约束(2)的唯一方法是打印基数1中的位数,因为从参数中取出的每个数字直接对应于Base中的单个字符1)。这可能不是你的意思,但这是一个解决方案:

// The accumulator starts at 0, then increases by 1 for each recursive call
void numOfDigits(unsigned int num) {
  if (num == 0) return;

  else {
    cout << 1
    numOfDigits(num / 10);
  }
}

N.B。此方法不会为numOfDigits(0)打印任何内容,如果我们想保留第if (num == 0) return;

,这是必要的