std::p ow 与整数类型进行比较,与整数类型进行比较

std::pow with integer parameters, comparing to an integer type

本文关键字:比较 类型 整数 ow std      更新时间:2023-10-16

根据 http://en.cppreference.com/w/cpp/numeric/math/pow,当std::pow与整数参数一起使用时,结果被提升为double

那么我的问题如下:

将整数类型与std::pow(int1, int2)的结果进行比较有多安全?例如,下面的if能否计算为 true?

std::size_t n = 1024;
if(n != std::pow(2, 10))
    cout << "Roundoff issues..." << endl;

也就是说,rhs 上的结果是否有可能类似于 1023.99...9,因此当转换为 size_t 时变为 1023?

我的猜测是,回应是一个很大的NO,但想知道确定。我在检查矩阵等的维度时使用这些比较,我不想在任何地方都使用std::round

你应该问这很有趣,因为 StackOverflow 上的其他人有一个问题,这个问题是由应用于小整数pow没有计算出他们平台上的明显结果这一事实引起的(另请参阅我的文章)。

所以是的,当pow应用于小整数时,参数和理想的数学结果都是完全可表示的。这不会强制exp的实现返回数学结果,因为没有标准指定pow不能被多个 ULP 不准确。至少有一个非常流行的平台默认提供了一个pow函数,该函数不会将pow(10, 2)计算为 100,但您可以自由地冒险pow(2, N)也许它总是会返回您有权期望的整数。

结果完全可表示时,对整数参数的pow应该始终为您提供正确的答案。 问题是,它没有。 有一些现代平台(例如,许多Linux发行版,无论是旧的还是最新的),它没有。 找到一堆SO问题并不难,人们给出了pow非常好的输入,它返回了一个非常错误的答案。

对于该特定示例,它应始终返回 false,特别是因为您使用的是 int 类型,因此不会有舍入错误。

您需要谨慎舍入误差的地方是当您比较两个不同的算术函数时,这些函数返回长小数的浮点数或双精度数。很多时候,由于不同的舍入和不同的操作,它们会返回为不相等。

正如几个答案所指出的那样,即使对于小数字,结果应该是完全可表示的,但也有一些低质量的实现。

对于使用 const 表达式的情况,例如:

std::pow(2, 10)

许多编译器将使用内置函数,例如gccclang将使用内置函数,这些函数可能会使用查找表或更简单的公式来处理这些琐碎的情况。对于上述情况,我们可以看到使用 godbolt gcc在编译时计算值:

movl    $1024, %esi     

这些结果更有可能是正确的,因为问题C:我用pow(10,2)和pow(10,j)得到了不同的结果,j=2;证明。