Если утверждение не оценивает TRUE, когда оно должно

У меня есть массив значений «x» (сетка для решателя PDE), что когда я передаю функцию, которая заполняет другой массив на основе этих значений x, определенное выражение, включающее одно значение x, не оценивается должным образом. Диапазон значений х равен -1: 1 с шагом 0,0125, а при х = -0,5 и при х = 0,5 мне нужно обрабатывать эти случаи иначе, чем другие значения. Однако приведенный ниже блок не может быть оценен как ИСТИНА для точки х = 0,5 (это нормально для х = -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;
}

Вот вывод для х = 0,5:

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

Таким образом, похоже, что выражение в операторе if должно возвращать TRUE, когда x = 0,5, хотя, конечно, это не точно 0,5, поскольку оно находится в пределах «лимита» диапазона. Какие-нибудь мысли??

-1

Решение

Ответ на оригинальный вопрос

Выражение в 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;

Пожалуйста, в будущем обязательно укажите правильный код в вопросе, который вы задаете.

3

Другие решения

Что ж, теперь, после того как вы исправили свой код, проблема очевидна. За 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). И это то, что заставляет его быть перехваченным первым if, Ваш позитив 0.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;
1

По вопросам рекламы [email protected]