Search code examples
c++templatesfloating-pointprecision

Floating Point Computation Precision in C++


I wanted to implement something like floating point precision where the template function controls the number of the digits after the point(.) (or the fraction)?

  template <typename T, unsigned int PRECISION = 4>
  constexpr T precision (T v) noexcept
      requires (is_floating_point_v<T>)
  {
    long digits = static_cast<long>(pow(10, PRECISION));
    long temp = v * digits;
    return 
        static_cast<T>(temp)
      / static_cast<T>(digits);
  }

Here a naive approach. I am not very happy with the pow function above to compute the digits. Is there something more Elegant? Like:

1e4, but the number *4* is not substitutable by *PRECISION*
10^PRECISION does not work

Is there something to express the pow function at compile time?

Alternative would be that, but I don't like the interface.

  template <typename T, unsigned int PRECISION = 10000>
  constexpr T precision (T v) noexcept
      requires (is_floating_point_v<T>)
  {
    long temp = v * PRECISION;
    return 
        static_cast<T>(temp)
      / static_cast<T>(PRECISION);
  }

Solution

  • My Solution to this question would be something like this:

      template <unsigned int EXP>
      constexpr long pow10x () noexcept
          requires (EXP >= 0)
      {
        long result = 1;
        for (unsigned int i=0; i<EXP; ++i)
          result*=10;
        return result;
      }
    
      template <unsigned int PRECISION = 4, typename T>
      constexpr T precision (T v) noexcept
          requires (is_floating_point_v<T> && PRECISION>=1 && PRECISION<=8)
      {
        long digits = pow10x<PRECISION>();
        long temp = v * digits;
        return 
            static_cast<T>(temp)
          / static_cast<T>(digits);
      }
    

    I thought there is something like a builtin pow function for integers as constexpr or even a simple expression. Well to write that function isn't difficult.