我理解为什么浮点数不能被比较,并且知道尾数和指数二进制表示,但我不是专家,今天我遇到了一些我没有得到的东西:
比方说让你有类似的东西:
float denominator, numerator, resultone, resulttwo;
resultone = numerator / denominator;
float buff = 1 / denominator;
resulttwo = numerator * buff;
Run Code Online (Sandbox Code Playgroud)
据我所知,不同的翻牌可以产生不同的结果,这并不罕见.但在某些边缘情况下,这两个结果似乎有很大不同.在我的GLSL代码中更具体地计算Cook-Torrance lighitng模型的Beckmann小平面斜率分布:
float a = 1 / (facetSlopeRMS * facetSlopeRMS * pow(clampedCosHalfNormal, 4));
float b = clampedCosHalfNormal * clampedCosHalfNormal - 1.0;
float c = facetSlopeRMS * facetSlopeRMS * clampedCosHalfNormal * clampedCosHalfNormal;
facetSlopeDistribution = a * exp(b/c);
Run Code Online (Sandbox Code Playgroud)
产生非常不同的结果
float a = (facetSlopeRMS * facetSlopeRMS * pow(clampedCosHalfNormal, 4));
facetDlopeDistribution = exp(b/c) / a;
Run Code Online (Sandbox Code Playgroud)
为什么呢?表达的第二种形式是有问题的.
如果我说尝试将表达式的第二种形式添加到颜色中,我会得到黑色,即使表达式应始终评估为正数.我是无限的吗?一个NaN?如果是这样的话?
我没有详细介绍你的数学,但是你必须意识到所有这些能力和指数都会轻易搞砸小错误.您应该尝试var用var + e(var)(在纸上,是)替换所有变量并导出总误差的表达式 - 而不是在步骤之间进行简化,因为这是错误的来源!
这也是计算流体动力学中非常常见的问题,如果您的网格未与模拟流体正确对齐,您可以观察到"数值扩散"之类的问题.
因此,要清楚地了解最大错误的来源,并尽可能重写方程以最大限度地减少数字错误.
编辑:澄清一个例子
假设你有一些变量x和一个表达式y=exp(x).x表示错误,e(x)并且与x(例如e(x)/x < 0.0001,但请注意,这取决于您使用的类型)相比较小.然后你可以这么说
e(y) = y(x+e(x)) - y(x)
e(y) ~ dy/dx * e(x) (for small e(x))
e(y) = exp(x) * e(x)
Run Code Online (Sandbox Code Playgroud)
所以有一个绝对误差的放大倍数exp(x),这意味着周围x=0真的没有问题(不是一个惊喜,因为在那一点上的斜率exp(x)等于x),但对于大的x你会注意到这一点.
那么相对误差就是
e(y)/y = e(y)/exp(x) = e(x)
Run Code Online (Sandbox Code Playgroud)
虽然相对错误x是
e(x)/x
Run Code Online (Sandbox Code Playgroud)
所以你添加了x相对误差的因子.