为什么除法产生的结果与浮点数乘以分数的结果截然不同

发布于 2024-10-10 03:35:33 字数 934 浏览 4 评论 0原文

我理解为什么浮点数不能进行比较,并且知道尾数和指数二进制表示,但我不是专家,今天我遇到了一些我不明白的事情:

也就是说,假设你有类似的东西:

float denominator, numerator, resultone, resulttwo;

resultone = numerator / denominator;

float buff = 1 / denominator;

resulttwo = numerator * buff;

给我的了解不同的失败会产生不同的结果,这并不罕见。但在某些边缘情况下,这两个结果似乎有很大不同。更具体地说,在我的 GLSL 代码中计算 Cook-Torrance 光照模型的 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);

非常不同的结果

float a = (facetSlopeRMS * facetSlopeRMS * pow(clampedCosHalfNormal, 4));
facetDlopeDistribution = exp(b/c) / a;

产生与为什么会产生 ?第二种表达形式是有问题的。

如果我说尝试将表达式的第二种形式添加到颜色中,我会得到黑色,即使表达式应始终计算为正数。我得到的是无穷大吗?一个NaN?如果是这样为什么?

I understand why floating point numbers can't be compared, and know about the mantissa and exponent binary representation, but I'm no expert and today I came across something I don't get:

Namely lets say you have something like:

float denominator, numerator, resultone, resulttwo;

resultone = numerator / denominator;

float buff = 1 / denominator;

resulttwo = numerator * buff;

To my knowledge different flops can yield different results and this is not unusual. But in some edge cases these two results seem to be vastly different. To be more specific in my GLSL code calculating the Beckmann facet slope distribution for the Cook-Torrance lighitng model:

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);

yields very very different results to

float a = (facetSlopeRMS * facetSlopeRMS * pow(clampedCosHalfNormal, 4));
facetDlopeDistribution = exp(b/c) / a;

Why does it? The second form of the expression is problematic.

If I say try to add the second form of the expression to a color I get blacks, even though the expression should always evaluate to a positive number. Am I getting an infinity? A NaN? if so why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梓梦 2024-10-17 03:35:33

我没有详细介绍你的数学,但你必须意识到,所有这些幂和指数很容易产生小错误。您应该尝试用 var + e(var) 替换所有变量 var (在纸面上,是的)并导出总误差的表达式 - 无需在步骤之间进行简化,因为这就是错误的来源!

这也是计算流体动力学中的一个非常常见的问题,如果您的网格与模拟流没有正确对齐,您可以观察到诸如“数值扩散”之类的问题。

因此,要清楚地了解最大误差的来源,并尽可能重写方程以最小化数字误差。

编辑:为了澄清,举一个例子

假设您有一些变量x和一个表达式y=exp(x)x 中的误差表示为 e(x),并且与 x 相比较小(例如 e(x)/x e(x)/x e(x)/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)

所以 exp(x) 的绝对误差被放大了,这意味着在 x=0 周围确实没有问题(这并不奇怪,因为在该点 exp(x) 的斜率等于 x) 的斜率,但对于大的 x 你会注意到这一点。

相对误差将是,

e(y)/y = e(y)/exp(x) = e(x)

x 中的相对误差为,

e(x)/x

因此您将 x 因子添加到相对误差中。

I didn't go through your mathematics in detail, but you must be aware that small errors get pumped up easily by all these powers and exponentials. You should try and substitute all variables var with var + e(var) (on paper, yes) and derive an expression for the total error - without simplifying in between steps, because that's where the error comes from!

This is also a very common problem in computational fluid dynamics, where you can observe things like 'numeric diffusion' if your grid isn't properly aligned with the simulated flow.

So get a clear grip on where the biggest errors come from, and rewrite equations where possible to minimize the numeric error.

edit: to clarify, an example

Say you have some variable x and an expression y=exp(x). The error in x is denoted e(x) and is small compared to x (say e(x)/x < 0.0001, but note that this depends on the type you are using). Then you could say that

e(y) = y(x+e(x)) - y(x)
e(y) ~ dy/dx * e(x)   (for small e(x))
e(y) = exp(x) * e(x)

So there's a magnification of the absolute error of exp(x), meaning that around x=0 there's really no issue (not a surprise, since at that point the slope of exp(x) equals that of x) , but for big x you will notice this.

The relative error would then be

e(y)/y = e(y)/exp(x) = e(x)

whilst the relative error in x was

e(x)/x

so you added a factor of x to the relative error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文