反转数字的最有效方法

The most efficient way to reverse a number

本文关键字:有效 方法 数字      更新时间:2023-10-16

我正在寻找一种有效的算法来反转数字,例如

输入: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算法通常非常有效。

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%。

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;
}
 //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-leng等(返回unsigned long-long。

取决于编译器实现的字符类型可以是有符号的,也可以是无符号的。

#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位无符号整数(987654321是最大输入(,并且你有4GB的可用内存(就效率而言,你是指内存吗?(,

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

应该足够快。假设存储器在100ns时间或200个周期内被访问,并且整数平均为7位,则其他解决方案如下:

  • 7次乘法
  • 7添加
  • 7模
  • 7个分区
  • 7次循环迭代,7次比较

若这些产生超过100纳秒/200个周期,那个么表会更快。例如,1个整数除法可以高达40个周期,所以我想这已经足够快了。如果重复输入,那么来自缓存的数据将具有更小的延迟。

但如果有数百万个反向操作并行,那么CPU计算绝对是比访问表更好的选择(使用矢量化计算循环+多线程可能会加速30x-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;
}