-1

我有一个“x”值数组(PDE 求解器的网格),当我传递给基于这些 x 值填充另一个数组的函数时,涉及一个 x 值的特定表达式无法正确评估。x 值范围是 -1:1,增量为 0.0125,在 x = -0.5 和 x = 0.5 时,我需要以不同于其他值的方式处理这些情况。但是,对于点 x = 0.5,下面的块无法评估为 TRUE(x = -0.5 可以)。这是问题块的精简片段,详细信息如下:

int N = 160;
double delta_x = 0.0125;
const double lims = 0.5 * delta_x;

for(int i = 0; i <= N; i++)
{                                
  if((x[i] < -0.5) || (x[i] > 0.5)) sol[i] = 0;
  else if( (abs(x[i] + 0.5) < lims) || (abs(x[i] - 0.5) < lims) )  sol[i] = 0.5;
  else sol[i] = 1;

  cout << setprecision(30) << "lims: " << lims << ", abs(x[i] - 0.5): " << abs(x[i] - 0.5) << endl;
  cout << "sol[" << i << "]: " << sol[i] << endl;                                                                                         
}

这是 x = 0.5 的输出:

lims: 0.00625000000000000034694469519536, abs(x[i] - 0.5): 1.11022302462515654042363166809e-16
sol[120]: 0

因此,看起来当 x = 0.5 时 if 语句中的表达式应该返回 TRUE,即使它当然不精确为 0.5,因为它在范围的“lims”内。有什么想法吗??

4

2 回答 2

3

回答原始问题

语句中的表达式if确实评估为真。如果没有,那么您将看不到问题中包含的输出。

FWIW,一个更简单的测试将是

abs(abs(x[i]) - 0.5) < lims

回答问题的最新版本

if((x[i] < -0.5) || (x[i] > 0.5)) sol[i] = 0;
else if( (abs(x[i] + 0.5) < lims) || (abs(x[i] - 0.5) < lims) )  sol[i] = 0.5;
else sol[i] = 1;

您说x[i]接近 0.5,但未设置sol[i]为 0.5,实际上将其设置为0. 在这种情况下,唯一合理的结论是x[i] > 0.5满足第一个条件:

if((x[i] < -0.5) || (x[i] > 0.5)) sol[i] = 0;

因此,您需要更改测试的顺序:

if( (abs(x[i] + 0.5) < lims) || (abs(x[i] - 0.5) < lims) )  sol[i] = 0.5;
else if((x[i] < -0.5) || (x[i] > 0.5)) sol[i] = 0;
else sol[i] = 1;

我会这样写:

if (abs(abs(x[i]) - 0.5) < lims)
    sol[i] = 0.5;
else if ((x[i] < -0.5) || (x[i] > 0.5)) 
    sol[i] = 0;
else 
    sol[i] = 1;

请确保在您提出的问题中包含正确的代码。

于 2013-11-08T22:44:10.547 回答
1

好吧,现在在您更正代码之后,问题就很明显了。因为x[i] = 0.5控制被第一个条件拦截

if((x[i] < -0.5) || (x[i] > 0.5)) sol[i] = 0;

它甚至没有得到你的abs评价。

浮点数并不总是精确的。虽然确实0.5可以精确表示,但它仅适用于您0.5直接分配或使用一些简单且特别稳定的评估来达到该值的情况(例如 的情况1.0/2)。在更复杂的情况下,您最终可能会得到不精确0.5的值(例如 的情况0.1 * 5)。这就是导致它被 first 拦截的原因if。你的 positive0.5是不精确的,恰好比精确的更大0.5

解决它的一种方法可能是将lim基于近似的比较放在首位,然后进行“精确”比较

if( (abs(x[i] + 0.5) < lims) || (abs(x[i] - 0.5) < lims) )  sol[i] = 0.5; 
else if((x[i] < -0.5) || (x[i] > 0.5)) sol[i] = 0;
else sol[i] = 1;
于 2013-11-08T22:53:33.153 回答