#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;
}
