For good fun, I attempted a generic implementation that supports any integral or floating point type supported by your compiler.
Be warned, there are a number of issues:
- reversing a floating point number is not well defined semantically (how to position the decimal separator? How do we handle exponential notation?)
- floating point types are frequently inexact (at least common IEEE formats are) and hence scaling the input will introduce artificial fractional digits. I have not taken much effort to do proper rounding, so some numbers will reverse into strange things (e.g. 123.0 could reverse into 992.1 instead of 321.0 (untested for this input, try some yourself))
- the implementation is laughably template-happy. Think of it as the instructional part of this playful answer.
Oh, uncomment the DEBUGTRACE definition to ... get debug tracing :)
#include <cmath>
#include <limits>
#include <iostream>
#define MAX_DECIMAL_FRACTION 5
#define DEBUGTRACE(x) // do { std::cerr << x; } while (false)
template <typename T, bool is_integer> struct reverse_impl;
template <typename T>
struct reverse_impl<T, true>
{
static T reverse(T input)
{
T output;
for (output = 0; input; input/=10)
output = (output * 10) + input % 10;
return output;
}
};
template <typename T>
struct reverse_impl<T, false>
{
static T reverse(T input)
{
if (std::abs(input) <= std::numeric_limits<T>::epsilon())
return T(0);
// scale input
int log10 = (int) (std::log(input)/std::log(T(10)));
input *= std::pow(10, MAX_DECIMAL_FRACTION);
input = std::floor(input);
input /= std::pow(10, log10+MAX_DECIMAL_FRACTION);
DEBUGTRACE("debug: scaled " << input << " digits: ");
int iteration = std::max(log10+MAX_DECIMAL_FRACTION, MAX_DECIMAL_FRACTION);
if (std::floor(input) < 1)
{
input *= 10;
iteration--;
}
T output;
for (output = T(0);
iteration-- && std::floor(input) >= 1;
input-=std::floor(input), input*=T(10))
{
output = (output / T(10)) + std::floor(input);
DEBUGTRACE(std::floor(input));
}
DEBUGTRACE(std::endl);
return output * std::pow(10, log10);
}
};
template <typename T>
T reverse(T input)
{
return reverse_impl<T, std::numeric_limits<T>::is_integer>::reverse(input);
}
int main()
{
std::cout << reverse(-123l) << std::endl;
std::cout << reverse(123ul) << std::endl;
std::cout << reverse(123456.0) << std::endl;
std::cout << reverse(0.027f) << std::endl;
return 0;
}