簡體   English   中英

反轉數字的最有效方法

[英]The most efficient way to reverse a number

我正在尋找一種有效的算法來反轉數字,例如

輸入: 3456789

輸出: 9876543

在 C++ 中,有很多帶有移位和位掩碼的選項,但最有效的方法是什么?

我的平台:x86_64

號碼范圍:XXX - XXXXXXXXXX(3 - 9 位數字)

編輯我輸入的最后一位數字永遠不會是零,所以沒有前導零問題。

像這樣的事情會起作用:

#include <iostream>

int main()
{
    long in = 3456789;
    long out = 0;
    while(in)
    {
        out *= 10;
        out += in % 10;
        in /= 10;
    }
    std::cout << out << std::endl;
    return 0;
}
#include <stdio.h>
unsigned int reverse(unsigned int val)
{
 unsigned int retval = 0;

 while( val > 0)
 {
     retval  = 10*retval + val%10;
     val     /= 10;
 }
 printf("returning - %d", retval);
 return retval;
}


int main()
{
    reverse(123);
}

您可以將數字轉換為字符串,然后使用 STL 算法反轉字符串。 下面的代碼應該工作:

 long number = 123456789;
 stringstream ss;
 ss << number;
 string numberToStr = ss.str();

 std::reverse(numberToStr.begin(), numberToStr.end());

 cout << atol(numberToStr.c_str());

您可能需要包含那些相關的頭文件。 我不確定這是否是最有效的方式,但 STL 算法通常非常有效。

int ans=0;
int rev(int n)
{
  ans=(ans+(n%10))*10; // using recursive function to reverse a number;
  if(n>9) 
    rev(n/10);
}

int main()
{
  int m=rev(456123); // m=32
  return 0;
}
static public int getReverseInt(int value) {
    int resultNumber = 0;
    for (int i = value; i != 0;) {
        int d = i / 10;
        resultNumber = (resultNumber - d) * 10 + i;
        i = d;
    }
    return resultNumber;
}

我認為這將是不使用asm的最快方法。 請注意, d*10 + i等價於i%10但速度要快得多,因為模比乘法慢 10 倍左右。
我測試了它,它比其他答案快了大約 25%。

 //Recursive method to find the reverse of a number  
 #include <bits/stdc++.h> 
    using namespace std; 
    int reversDigits(int num) 
    { 
    static int rev_num = 0; 
    static int base_pos = 1; 
    if(num > 0) 
    { 
        reversDigits(num/10); 
        rev_num += (num%10)*base_pos; 
        base_pos *= 10; 
    } 
    return rev_num; 
    } 
    int main() 
    { 
        int num = 4562; 
        cout << "Reverse  " << reversDigits(num); 
    } ``
// recursive method to reverse number. lang = java
static void reverseNumber(int number){
    // number == 0 is the base case
    if(number !=0 ){
        //recursive case
        System.out.print(number %10);
        reverseNumber(number /10);
    }
}

此解決方案效率不高,但確實解決了問題並且很有用。 它為任何有符號整數(int、long、long long 等)返回 long long,為任何無符號整數(unsigned int、unsigned long、unsigned long long 等)返回 unsigned long long。

取決於編譯器實現的 char 類型可以是有符號或無符號的。

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


template <bool B>
struct SignedNumber
{
};

template <>
struct SignedNumber<true>
{
    typedef long long type;
};

template <>
struct SignedNumber<false>
{
    typedef unsigned long long type;
};

template <typename TNumber = int,
          typename TResult = typename SignedNumber<std::is_signed<TNumber>::value>::type,
          typename = typename std::void_t<std::enable_if_t<std::numeric_limits<TNumber>::is_integer>>>
TResult ReverseNumber(TNumber value)
{
    bool isSigned = std::is_signed_v<TNumber>;
    int sign = 1;
    if (value < 0)
    {
        value *= -1;
        sign = -1;
    }
    std::string str = std::to_string(value);
    std::reverse(str.begin(), str.end());
    return isSigned ? std::stoll(str) * sign : std::stoull(str) * sign;
}

int main()
{
    std::cout << ReverseNumber(true) << std::endl; //bool -> unsigned long long
    std::cout << ReverseNumber(false) << std::endl; //bool -> unsigned long long
    std::cout << ReverseNumber('@') << std::endl; //char -> long long or unsigned long long 
    std::cout << ReverseNumber(46) << std::endl; //int -> long long
    std::cout << ReverseNumber(-46) << std::endl; //int -> long long
    std::cout << ReverseNumber(46U) << std::endl; //unsigned int -> unsigned long long
    std::cout << ReverseNumber(46L) << std::endl; //long -> long long
    std::cout << ReverseNumber(-46LL) << std::endl; //long long -> long long
    std::cout << ReverseNumber(46UL) << std::endl; //unsigned long -> unsigned long long
    std::cout << ReverseNumber(4600ULL) << std::endl; //unsigned long long -> unsigned long long
}

輸出

1
0
64
64
-64
64
64
-64
64
64

測試這段代碼
https://repl.it/@JomaCorpFX/IntegerToStr#main.cpp

如果它是 32 位無符號整數(987,654,321 是最大輸入),並且如果您有 4GB 可用內存(按效率來說,您也是指內存嗎?),

result=table[value]; // index 12345 has 54321, index 123 has 321

應該足夠快。 假設以 100 ns 時間或 200 個周期訪問內存並且整數平均為 7 位,其他解決方案有這些:

  • 7 次乘法,
  • 7 添加,
  • 7 模,
  • 7個部門,
  • 7 次循環迭代,7 次比較

如果這些超過 100 納秒/200 個周期,那么 table 會更快。 例如,1 個整數除法可以高達 40 個周期,所以我想這已經足夠快了。 如果重復輸入,那么來自緩存的數據將具有更少的延遲。

但是如果有數百萬個並行的逆向操作,那么 CPU 計算絕對是比訪問表更好的選擇(使用矢量化計算循環 + 多線程可能會提高 30 倍-100 倍的加速)。 它有每個核心和多個核心的多個管道。 您甚至可以選擇帶有 GPU 的 CUDA/OpenCL 以獲得額外的吞吐量,並且這種從其他答案中得到的反向解決方案看起來非常令人尷尬地可並行化,因為 1 個輸入獨立於其他輸入進行計算。

這是最簡單的一種:

#include<iostream>
using namespace std;

int main()
{
int number, reversed=0;
cout<<"Input a number to Reverse: ";
cin>>number;
    while(number!=0)
  {
    reversed= reversed*10;
    reversed=reversed+number%10;
    number=number/10;
  }
cout<<"Reversed number is: "<<reversed<<endl;

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM