pow(1, inf) == nan?

pow(1, inf) == nan?

本文关键字:nan inf pow      更新时间:2023-10-16

我注意到我的一个计算着色器中有一些奇怪的行为,它们会意外地返回nan。仔细调查后,我发现pow就是罪魁祸首:

pow(1, inf) == NaN

从C/c++的角度来看,我希望pow(1, inf) == 1:

pow(+1, exponent)对于任何指数都返回1,即使指数是NaN

GLSL的pow定义这个输入吗?

我只在规范中发现base < 0base == 0 && exponent <= 0的常见异常。

@Damon的回答很接近,但是抄袭了spec中的一个错误:

pow(x, y) == exp2(x *  log2 (y))

其中x和y交换了。应该是

pow(x, y) == exp2(y *  log2 (x))

(测试例pow(2, 3))

使用正确的公式我们得到

pow(1, inf) == exp2(inf * log2(1)) == exp2(inf * 0) == exp2(nan) == nan

虽然计算着色器暗示您使用GPU和GLSL版本(> 1.30)来执行IEEE兼容的浮点数学,但不幸的是,这不是您可以理所当然的事情。所以…这里有龙。

您从c++的角度引用c++参考的推理是合理和正确的,但它省略了一个小而重要的句子:"如果实现支持IEEE浮点运算(IEC 60559),"。这句话强调了它既不是c++的要求(只是巧合,因为IEEE 754要求它,而通常 c++实现符合IEEE),也不是严格的保证(完全允许c++实现而不是实现IEEE 754)。

进一步,GLSL 不是 c++。对于算术来说,这可能会让人感到惊讶,因为尽管它显然不是同一种语言,但人们可以期望数学仍然是一样的,不是吗?

嗯,没有。pow(x, y)在GLSL中被定义为exp2(x*log2(x))(尽管在线手册页所基于的8.2没有明确地这样说)。它从前面提到的4.7.1中描述的表达式继承了精度。没有说明pow(1, x)等于1

现在,用可能正确的中间结果展开上述表达式,正确的结果应该是+INF,因为log2(+INF) = +INF1*+INF仍然是+INFexp2(+INF) = +INF
但是,标准并没有真正定义这个。它只显式(un)定义零指数。