【问题标题】:How to move the first digit to the end of a number in c++?如何将第一个数字移动到c ++中数字的末尾?
【发布时间】:2018-02-02 13:49:01
【问题描述】:

代码如下:

#include <iostream>
using namespace std;

int main ()
{
    int n;
    cin >> n;
    int first = n;

    while (first>=10)
    {
      first/=10;
    }

    cout << first << endl;
}

在上面的代码中,我试图获取一个正数的第一个数字,我想做的是把它放在最后一个数字之后,例如: 1934 -&gt; 9341.

【问题讨论】:

  • 一定要使用整数类型吗? std::stringstd::rotate 让这一切变得非常简单。
  • @MichaëlvanderHaven 不是真的,因为 OP 不想交换数字。
  • 它不会先与最后交换,如果是这样,1934 将是 4931
  • @DerekCole 我不得不问——如果你不能先在纸上弄清楚,为什么还要写代码?
  • @Ron 是的,这不是重复的。第一个问题是1234怎么办-->4231,这个问怎么办1234-->2341

标签: c++


【解决方案1】:

使用std::to_string将数字转换为字符串,使用std::rotate执行左旋转并使用std::stoull函数转换回数字:

std::string s = std::to_string(n);
std::rotate(s.begin(), s.begin() + 1, s.end());
n = std::stoull(s);

包含所有标题:

#include <iostream>
#include <string>
#include <algorithm>

int main() {
    unsigned long long n = 1934;
    std::string s = std::to_string(n);
    std::rotate(s.begin(), s.begin() + 1, s.end()); // left rotation
    n = std::stoull(s);
    std::cout << n; // 9341
}

【讨论】:

  • OP 想要来自1234523451,而不是52341
  • @Ron 逻辑很好 :-)
【解决方案2】:

这是一个不使用字符串或浮点函数/算术的简单解决方案。使用pow() 等函数可能会遇到in this question 所述的问题。

 #include <iostream>

 int main()
 {
    unsigned long long n = 1934L;

    // save the original
    unsigned long long final_number = n;

    // multiplying factor
    unsigned long long mult = 1;

    // start by making sure we do not loop one too many times to 
    // calculate the multiplier
    n /= 10;

    while (n > 0)
    {
        // determines the multiplication factor after the loop 
        mult *= 10; 

        // strip off digit from number
        n /= 10;
    }

    // create the final number from the original and the multiplication factor
    final_number = (final_number % mult) * 10 + final_number / mult;
    std::cout << final_number << "\n";
}

Live Example

基本上我们通过循环计算多少位数,同时将乘数增加10。然后在循环之后,使用模数、乘法、除法和加法来构造数字。

例如,在循环之后,final_number 将是

(1934 % 1000) * 10 + 1934 / 1000 =
934 * 10 + 1934 / 1000 = 
9340 + 1934 / 1000 =
9340 + 1 =
9341

注意:我查看了生成的汇编语言here,很惊讶编译器能够弄清楚代码的意图,并在编译时计算出 9341。我怀疑pow 解决方案或浮点方法会产生这些结果。

【讨论】:

  • 小角限制:(final_number % mult) * 10 可能溢出。
  • mult 类型应该匹配 final_number 类型。
【解决方案3】:

您可以修改循环以不仅获取第一位数字,还可以同时计算位数(这是循环的迭代次数)。然后,酌情使用%* 10修改n

【讨论】:

    【解决方案4】:

    假设我们有正整数作为输入。

    1. 获取最重要的数字

      MSD=floor(X/pow(10,floor(log10(X))));
      
    2. 获取剩余的数字

      Rest=X%pow(10,floor(log10(X)));
      
    3. 将其余部分提高到适当的值

      Rest=Rest*10;
      
    4. 添加前一个最重要的数字

      Y=Rest+MSD.
      

    分解示例:

    X=54321;                             // 54321
                             log10(X)    // 4.734...
                       floor(...     )   // 4
                pow(10,...            )  // 10000
              X/...                      // 5.4321
    MSD=floor(...                      );// 5
               pow(10,floor(log10(X))    // 10000
             X%...                       // 4321
          10*...                         // 43210
    Y=MSD+...                        ;   // 43215
    

    【讨论】:

    • 呃,不是^Bitwise XOR吗?你的意思是使用pow()
    • @Drise 感谢您的指出。我习惯了不同的语言。此外,正如 Phillip Schmid 使用的那样,基于 C 的语言默认情况下会转换整数,因此不需要 floor(),但我将其用作独立于语言的答案。 ^ 是 MATLAB 中的强大功能,我主要使用的是...
    • 实际上,如果我没记错的话,“向下舍入整数 [除]”不是您在 C/C++ 中寻找的内容,它是 truncation towards zero
    • MSD=floor(X/pow(10,floor(log10(X)))); 在数学上是正确的,但在 X 的值接近 D * some_power_of_10Xdouble 更精确(例如 64 位)时,计算上容易出现舍入错误.
    【解决方案5】:

    我首先要说我不是 C++ 程序员。所以我并不是说这段代码很好,只是它可以工作并且遵循你的方法!

    在向您展示代码的最小编辑以获得您想要的内容之前,我将引导您完成操作,并举例说明:我们假设您要将 2345 转换为 3452

    • 您已从查找输入 (n) 的最高有效数字 (first) 开始
    • 您现在需要从前面删除该数字。这很简单:
      • 我们已经有一个循环,我们将 first 除以 10,所以让我们重用它
      • 创建一个从 1 开始的数字(我们称之为 bigness),然后在每个循环中将其乘以 10。
    • 您现在有 3 个号码:
      • n = 2345
      • first = 2
      • bigness = 1000

    这就是你所需要的!

    你可以从n中减去first * bigness来去掉前面的数字——345

    您可以将其乘以 10 并添加 first 以将数字放在末尾 - 3452

    这是结束代码:

    #include <iostream>
    using namespace std;
    
    int main ()
    {
        int n;
        cin >> n;
        int first = n;
        int bigness = 1;
    
        while (first >= 10)
        {
            first /= 10;
            bigness *= 10;
        }
    
        n = n - (first * bigness);
        n = (n * 10) + first;
    
        cout << n;
    }
    

    请注意,这会给像20000 这样的数字留下问题——它们变成2,因为我们的代码不知道我们想要00002。使用 printf 之类的东西来维护位数很容易解决这个问题,但这意味着循环中的另一个变量,从 1 开始,计算我们需要的位数。

    【讨论】:

    • (n * 10) + first; 可能会溢出像n = 1987654321 这样的起始值。
    • 是的 - 使用整数的缺点。正如我在第一行中提到的,我并不是说它是好的代码 - 只是它从 OP 的起点在逻辑上遵循。我很确定这对于大量意外输入(至少可以说是负数、小数和非数字输入)会严重失败。
    【解决方案6】:

    由于 C++ 整数最多有十几个数字,代码可以使用简单的递归解决方案:

    unsigned reverse_helper(unsigned x) {
      if (x < 10) {
        return x;
      }
      unsigned last = reverse_helper(x/10);
      cout << x%10;
      return last;
    }
    
    void reverse(unsigned x) {
      cout << reverse_helper(x)) << endl;
    }
    

    测试代码

    int main(void) {
      reverse(0);
      reverse(9);
      reverse(10);
      reverse(1934);
      reverse(1234567890);
    }
    
    0
    9
    01
    9341
    2345678901
    

    【讨论】:

      【解决方案7】:

      不使用字符串的解决方案。它确实使用了std::stack,它可能不会获得任何效率奖,但它应该非常简单易懂。

      #include <stack>
      #include <iostream>
      
      int main()
      {
          int num = 1934;
          std::stack<int> digits;
      
          // Break the number into digits, pushing them onto a stack
          while (num)
          {
              auto digit = num % 10;
              digits.push(digit);
              num /= 10;
          }
      
          // Get the first digit from the top of the stack and save it
          auto first = 0;
          if (!digits.empty())
          {
              first = digits.top();
              digits.pop();
          }
      
          // Pop the remaining digits off the stack and print them
          while (!digits.empty())
          {
              std::cout << digits.top();
              digits.pop();
          }
      
          // Print the first digit on the end
          std::cout << first << '\n';
      }
      

      编辑:修复了 num == 0 的错误。请注意,负数处理不正确,但我不确定这种情况下所需的行为是什么。使用unsigned 代替int 可能是个好主意。

      【讨论】:

      • num == 0 时,digits.top(); 是否可靠地返回 0?
      • @chux:不,它非常可靠地调用了未定义的行为。它也不适用于负数。
      • @chux:现在应该修复了。感谢代码审查!
      • 替代方案:while (num) { auto digit = num % 10; digits.push(digit); num /= 10; } --> do { auto digit = num % 10; digits.push(digit); num /= 10; } while (num); 确保堆栈中至少有一个。那么if (!digits.empty()) 就不需要了。
      【解决方案8】:

      这是一个不使用字符串的版本。

      //There's also a builtin log10 function but you can write your own if you want to:
      int log10(int nbr) {
          return log(n) / log(10);
      }
      
      //....
      int first_digit = n / (int)pow(10, log10(n));
      int everything_else = n % (int)pow(10, log10(n));
      

      确保包含math.h

      它使用了 float -&gt; int 转换在 C++ 中总是向零舍入这一事实。所以(int)log10(101) 将返回 2,因此pow(10, (log10(n))) 将舍入每个向下舍入到10/100/1000/etc 的数字。剩下的只是简单的除法和取模。

      【讨论】:

      • 我已经添加了一条评论,如果这是您的批评,那么还有一个内置的 log10 函数。如果这不是你的意思,请详细说明。该解决方案应该比使用字符串的任何答案都快很多
      • 也许将 pow() 包装在 floor() 中只是为了使其明确?
      • log(n)log(10) 返回真实数学 log 的近似数学结果。将超越函数(如log(), exp())的结果转换为int 可能会从x.9999999999999... 意外返回int
      【解决方案9】:

      这是编程和数学+编程竞赛的典型元素,所以我不会给出完整的答案,但我会说:

      • 几乎可以肯定,使用字符串不是最节省 CPU 时间的解决方案。
      • 您已经有了第一个(最重要的)数字。修改问题中的代码,您可以计算 10 的适当幂以从原始数字中减去第一位数字。
      • 请注意,n * 10 将数字向左移动并留下一个“洞”,您可以稍后根据需要进行填充。 (如果这对您来说很明显,我们深表歉意。)
      • 您可以只使用整数运算、没有浮点数、没有函数(logexp)来完成所有这些操作。其他解决方案已经展示了完整的算法;我强调你可以不用浮点数和日志。
      • 小心使用 0 和负数。

      【讨论】:

        【解决方案10】:

        由于std::string 已经有很多解决方案,我尝试不使用它,这是我的结果。 我希望这会有所帮助。

        #include <iostream>
        #include <cmath>
        using namespace std;
        
        int removeFirst(int n)
        {
            int tmp(0);
            for (int i(0);; ++i)
            {
                int m = n % 10;
                n /= 10;
                if (n != 0)
                {
                    tmp += pow(10, i) * m;
                }
                else
                {
                    break;
                }
            }
            return tmp;
        }
        
        int main()
        {
            int input, first, withoutFirst;
            cin >> input;
            withoutFirst = removeFirst(input);
        
            while (input >= 10)
            {
                input /= 10;
            }
            first = input;
        
            cout << withoutFirst << first << endl;
        }
        

        帮助使用:trying to remove first digit of any number

        问候。

        【讨论】:

        • 问题是数字不应该颠倒,只是最左边的数字移动到最右边的数字。
        • @PaulMcKenzie 我明白了,我要更改代码。谢谢,没看到。
        • 另外,已经有两种字符串的解决方案了,这个问题不用字符串也可以解决。
        • @PaulMcKenzie 是的,这是一个没有字符串的解决方案。
        • 除了作为练习之外,我不明白为什么人们更愿意在循环中使用std::pow 而不是std::to_string+std::stoull。迭代浮点运算通常比将整数转换为字符串并返回要慢得多。
        【解决方案11】:

        string 已经有一些答案,到目前为止还有一个答案没有string。使用string 是最有效的一种。但是,如果 OP 想通过计算方法和使用整数来解决它,这就是我尝试过的。当不使用string 时,我猜这种解决方案效率更高。

        #include <iostream>
        #include <math.h>
        using namespace std;
        
        int main ()
        {
            int n, digits, firstDigit, firstDigitToLast;
            cin >> n;
        
            digits = (int)log10(n);
            firstDigit = (int)(n / pow(10, digits));
            firstDigitToLast = n % ((int) pow(10, digits));
            firstDigitToLast *= 10;
            firstDigitToLast += firstDigit;
        
            cout << firstDigitToLast << endl;
        }
        

        【讨论】:

          【解决方案12】:
          std::string s = std::to_string(n);
          s += s.front();
          s.erase(0, 1);
          n = std::stoull(s);
          

          这个:

          1. 将数字转换为字符串。
          2. 将第一个字符添加到末尾。
          3. 删除第一个字符。
          4. 并将结果转换回unsigned long long

          Live Example

          【讨论】:

            【解决方案13】:

            我会使用log10%

            int num = 8907;
            
            int num_digits = log10(num); // Value of 3 for 8907
            int pwr = pow(10, num_digits); // Value of 1000 for 8907
            int ones_place = num % 10; // 7
            int bigs_place = num / pwr; // 8
            
            int cur_msd = bigs_place * pwr; // 8000
            int new_msd = ones_place * pwr; // 7000
            
            num -= cur_msd;
            num += new_msd;
            num -= ones_place;
            num += bigs_place;
            cout << num << endl;
            

            此代码为我输出 7908。


            编辑

            我看错了帖子。我以为你想要交换 LSB 和 MSB,而不是旋转。

            将最后 4 行替换为

            num -= cur_msd;
            num *= 10;
            num += bigs_place;
            

            【讨论】:

              【解决方案14】:

              虽然循环和字符串可能非常有效,但在这种情况下它们是完全没有必要的。
              你只需要一点数学:

              #include <math.h>       // log10, pow, floor
              #include <stdio.h>      // printf
              int main ()
              {
                int n = 6945;
                int p = pow(10,floor(log10(n)));
                int output = (n - ((n/p)%10)*p)*10+((n/p)%10);
                printf("%i",output);       // outputs 9456
              }
              

              这个想法是首先找到数字有多少位 (floor(log10(n))),然后通过将输入除以 10 的幂 (pow(10,floor(log10(n)))) 模 10 来获得最高有效位。我们将存储这个在名为pint 中。

              在这种情况下,这给了我们6。然后我们从n 中减去6 乘以p 得到剩余的数字(在我们的例子中为945),然后我们将其乘以十并加上6,得到我们的最终答案9456

              【讨论】:

                【解决方案15】:

                这就是我的做法

                #include<stdio.h>
                #include<math.h>
                int main()
                {
                int a,g=10,m=1,c,num;
                printf("enter the number : ");
                scanf("%d",&a);
                c=log10(a);
                num=num+((a%10)*pow(10,c));
                a=a/10;
                c=log10(a);
                while(m<=c){
                    if(m==c){
                        num=num+((a%10)*g)+a/10;
                        break;
                    }
                    else{
                        num=num+((a%10)*g);
                        g=g*10;
                        a=a/10;
                        m=m+1;
                    }
                }
                printf("%d",num);
                }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2017-04-12
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-01-30
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多