如何强制pow(float,int)返回float

Mic*_*hal 10 c++ pow c++11

float pow(float base, int iexp )在C++ 11中删除了重载的函数,现在pow返回一个double.在我的程序中,我计算了很多这些(单精度),我对如何做到最有效的方式感兴趣.

是否有一些特殊功能(在标准库或任何其他)具有上述签名?

如果没有,在任何其他操作(将其他所有内容都投入)或者转换为使用重载函数之前,是否更好(在单精度方面的性能方面)显式地pow转换结果?floatdoubleiexpfloatfloat pow(float base, float exp)

编辑:为什么我需要float和不使用double

主要原因是RAM - 我需要数十或数百GB,因此这种减少是巨大的优势.所以我需要float得到float.现在我需要最有效的方法来实现这一目标(减少演员阵容,使用已经优化的算法等).

iva*_*ult 2

fpow您可以轻松地使用乘方和平方来编写自己的代码。

float my_fpow(float base, unsigned exp)
{
    float result = 1.f;
    while (exp)
    {
        if (exp & 1)
            result *= base;
        exp >>= 1;
        base *= base;
    }

    return result;
}
Run Code Online (Sandbox Code Playgroud)


无聊部分:

该算法提供了最好的精度,可以在|base|float时使用类型进行存档。> 1

证明:

让我们来计算基数 和指数pow(a, n)在哪里。 让我们定义b 1 =a 1b 2 =a 2b 3 =a 4b 4 =a 8等。an

那么a n是所有这样的b i 的乘积,其中第i 位在n中设置。

所以我们已经订购了集合B={b k1 ,b k1 ,...,b kn }并且对于任何j,位 k j被设置在n中。

以下明显的算法A可用于舍入误差最小化:

  • 如果B包含单个元素,则它是结果
  • B中选取两个具有最小模数的元素pq
  • 将它们从B中删除
  • 计算乘积s = p*q并将其放入B
  • 转到第一步

现在,让我们证明B中的元素可以从左到右相乘,而不会损失准确性。它来自这样的事实:

b j > b 1 *b 2 *...*b j-1

因为b j =b j-1 *b j-1 =b j-1 *b j-2 *b j-2 =...=b j-1 *b j-2 *...*b 1 *乙1

因为,b 1 = a 1 = a及其模大于 1:

b j > b 1 *b 2 *...*b j-1

因此我们可以得出结论,在从左到右的乘法过程中,累加器变量小于B中的任何元素。

然后,表达式result *= base;(当然除了第一次迭代)将B中的两个最小数字相乘,因此舍入误差最小。因此,代码采用算法A

  • 这将不如任何“pow”重载准确,并且您没有提供任何表明它比标准“pow”更快的数字。 (3认同)
  • 因为这引入了额外的舍入:它在每次单独的乘法之后进行舍入。你是说额外的四舍五入肯定不会影响结果吗?如果是这样,如果您可以在答案中包含原因,我将很乐意删除我的反对票。但是当我用随机数进行测试时,我*确实*看到了答案不同的情况。 (2认同)
  • 您可以做的是使用“double”进行内部计算并转换回“float”。单独而言,“double”通常并不比“float”慢(除法除外)。`float` <-> `double` 转换速度很快,并且每个方向只发生一次。 (2认同)