2014-11-15 132 views
4

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

我的问题是那么下面:

如何安全是比较有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

+0

2,10和1024都可以完全用'double'表示。你应该没问题,只要输入和输出符合53位(假设IEEE-754是双精度) – Praetorian

+1

@Praetorian你应该告诉user1257。 http://stackoverflow.com/questions/15851636/is-this-a-g-bug –

+0

@PascalCuoq这很有趣,也很可怕。我无法在gcc4.4.7,4.8,4.9或MinGW gcc4.9上重现;但很好意识到这个问题。谢谢。 – Praetorian

回答

4

很有趣的是,你应该问,因为someone else on StackOverflow了,是由张女士pow适用于小整数并没有计算他们的平台上有明显的结果造成了问题(见我的writeup)。

所以是的,当将pow应用于小整数时,参数和理想的数学结果都可以精确表示。这不会强制执行exp来返回数学结果,因为没有标准指定pow不能由多个ULP不准确。至少有一个非常受欢迎的平台默认提供pow函数,它不会将pow(10, 2)计算为100,但是您可以随意使用pow(2, N),也许它总是会返回您有权期待的整数。

+5

除非你不应该使用'pow(2,N)',因为'ldexp(1,N)'更好(更快,保证精确的结果) –

+0

@BenVoigt很高兴知道,谢谢,虽然我给了2^N作为例。实际上,我使用D^N,其中D可以是任何整数,而不仅仅是2。 – vsoftco

0

对于这个特定的例子,它应该总是返回false,尤其是因为您使用的是int类型,所以不会有舍入错误。

当你比较两个不同的算术函数返回浮点数或加倍长小数时,你会对舍入错误谨慎的地方是。很多时候,由于不同的舍入和不同的操作发生,他们会返回不平等。

3

pow当结果是完全可表示的整数参数应该一直给你正确的答案。问题是,事实并非如此。有很多现代化的平台(大量的Linux发行版,例如旧版和近期版),而不是。找到一堆SO问题并不难,因为人们给出的输入非常好,并且它返回了一个可怕的错误答案。

0

由于几个答案已经指出,即使对于小数字的结果应该是完全可以表示的有一些低质量的实现。

对于您正在使用常量的CASE表达式如:

std::pow(2, 10) 

许多编译器将使用builtin functions例如既gccclang将使用这可能会使用类似的查找表或内建函数这些琐碎案件的一个更简单的公式。我们可以看到使用godboltgcc在编译时计算值与上述情况:

movl $1024, %esi  

这些结果更可能是正确的,因为这个问题C: i got different results with pow(10,2) and pow(10,j), j=2;演示。