2013-11-08 6 views
-1

У меня есть массив значений «x» (сетка для решателя PDE), который, когда я перехожу к функции, которая заполняет другой массив на основе этих значений x, одно значение x не оценивается должным образом. Диапазон значений x равен -1: 1 с шагом 0,0125, а при x = -0,5 и при x = 0,5 мне нужно обрабатывать эти случаи иначе, чем другие значения. Однако нижеприведенный блок не может оценить TRUE для точки x = 0,5 (это нормально для x = -0,5). Вот урезанная фрагмент блока проблем, с деталями следовать:Если оператор не оценивает TRUE, когда он должен

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

Это конечно выглядит совсем по-одной ошибки для меня. Конечно, это должно быть

+1

Просто проверка - вы включаете 'cmath.h'? 'abs' только перегружен для удваивания в том, что' stdlib' объявляет int-only 'abs'. – usr2564301

+1

Просьба уточнить, что не работает, как вы ожидаете. В примере вывода 1е-16, безусловно, находится в пределах допуска «lims». – MooseBoys

ответ

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; 

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

+1

Точно. Вывод, указанный в вопросе, был создан для 'x = 0,5'. Однако ОП утверждает, что для 'x = 0,5'' if' не вводится. Вопрос, как сказано, противоречит самому себе. – AnT

+0

@ AndreyT Спасибо, что заметили это, моя ошибка. Я пытался сделать это проще, но тогда он не показывал ошибку. Я только что отредактировал его, чтобы ошибка была результатом. – bcf

+0

@ Давид Хеффернон - Спасибо! Я просто понял, что мне нужно просто сначала проверить эту проблему if-statement. – bcf

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). И именно это заставляет его перехватываться этим первым 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; 
Смежные вопросы