【问题标题】:pow(1, inf) == nan?pow(1, inf) == 南?
【发布时间】:2015-11-02 03:12:53
【问题描述】:

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

pow(1, inf) == NaN

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

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

是否为此输入定义了 GLSL 的 pow

我只在规范中发现了base < 0base == 0 && exponent <= 0 的常见例外情况。

【问题讨论】:

  • 1/0,嗯?被零除?无穷大似乎是正确的结果,而 NaN 作为无穷大的力量是不可能的。
  • @Vallentin:我只能告诉你我所看到的。 1/0 没有编译器错误(或警告)以及来自 pow 的 1 的结果。如果你有更好的方法create INF inside GLSL 告诉我。
  • 除以零不需要抛出错误,因为无穷大是可接受的结果。因此 x^infinity 再次等于预期的 NaN。我的意思是,我看不出问题出在哪里,因为结果是有道理的。
  • @Vallentin 从数学的角度来看,我希望 1^infinity 为 1,x^infinity 为 0 1 为无穷大。 NaN 恕我直言的唯一地方是负数的无穷次幂。
  • @Nobody 从数学的角度来看,1^Infinity 不是 1。mathforum.org/library/drmath/view/56006.html

标签: c++ opengl glsl nvidia


【解决方案1】:

@Damon's answer 很接近,但从规范中复制了一个错误:

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

【讨论】:

    【解决方案2】:

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

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

    此外,GLSL 不是 C++。这可能会让算术感到惊讶,因为尽管它显然不是同一种语言,但人们可以期望数学仍然可以正常工作,不是吗?

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

    现在,用可能正确中间结果扩展上述表达式,正确的结果应该是+INF,因为log2(+INF) = +INF1*+INF仍然是+INF,和@987654330 @.
    但是,标准并没有真正定义这一点。它仅显式(取消)定义零指数。

    【讨论】:

    • 刚刚在spec 中偶然发现了这个确切的 (exp2(x*log2(y))) 段落。该死的,只是另一件事要绊倒。
    • 现在我想起来了,我意识到你的回答解释了为什么在 GLSL 中使用 pow(1, inf) == INF,但没有解释为什么它是我的问题中的 NaN。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-24
    • 2020-01-21
    • 2012-04-15
    • 1970-01-01
    相关资源
    最近更新 更多