C++ 中的浮点计算精度

Floating Point Computation Precision in C++

提问人:Code4Fun 提问时间:7/7/2023 最后编辑:AmolgorithmCode4Fun 更新时间:7/7/2023 访问量:94

问:

我想实现类似浮点精度的东西,其中模板函数控制 point(.) 之后的位数。(或分数)?

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

这是一个幼稚的方法。我对上面的 pow 函数计算数字不是很满意。还有比这更优雅的吗?喜欢:

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

在编译时有什么东西可以表达 pow 函数吗?

另一种选择是,但我不喜欢界面。

  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);
  }
C++ 模板 浮点 精度

评论

0赞 Jarod42 7/7/2023
您可以为非浮点 .constexprconstevalpow
0赞 Toby Speight 7/7/2023
你写的可能是定点的,而不是浮动的。有一些向 移动,但对于整数幂,编写自己的实现很容易。constexpr std::pow()constexpr
3赞 Jarod42 7/7/2023
正如可推导的那样,可能更容易使用。Ttemplate <unsigned int PRECISION = 4, typename T>
1赞 Eric Postpischil 7/7/2023
像这样的功能通常是一个坏主意,除非在特定的有限情况下或由专家精心制作,否则不会做你想做的事。在使用基于二进制的浮点的 C 实现中,几乎所有浮点都使用,实际上不可能“控制点后面的位数”,因为像 1.234 这样的数字不能以格式表示(只是接近的东西)。此外,舍入问题有时会导致以下截断为 的意外结果。v * digitslong
0赞 Code4Fun 7/7/2023
这是真的。但是我想要一些精度较低的东西,只有 4 到 8 位数字。这应该适用于浮点或双精度。对于我的担忧,我认为已经足够了。你知道更好的选择吗?

答:

0赞 Code4Fun 7/7/2023 #1

我对这个问题的解决方案是这样的:

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

我以为有一个内置的 pow 函数,用于整数作为 constexpr 甚至一个简单的表达式。好吧,编写该函数并不难。

评论

0赞 Code4Fun 7/7/2023
你是对的。我把它拿出来了