Странное поведение Labwindows при добавлении ДВОЙНЫХ номеров
Я запускаю следующий блок кода внутри функции CALLBACK для таймера.
if (start_value <= end_value)
{
start_value += increment_value;
}
else
{
return 0;
}
все три переменные определены как DOUBLE.
Double start_value = 26.0;
Double end_value = 28.0;
increment_value = 0.1;
при добавлении increment_value к start_value значение переменной start_value не просто отражает ожидаемый результат добавления. Например, когда start_value равно 26.0, после одного добавления значение start_value равно 26.10000000001. Конечный 1 вызывает проблемы позже в коде, потому что, когда ожидаемый результат сравнения, как ожидается, будет ИСТИНА, он оценивается как ложный из-за конечного 1. Почему это происходит?
1 ответ
Эшан, The ==
Оператор ищет точное совпадение и должен использоваться исключительно для целочисленных сравнений (где возможно точное). Итак, "почему это происходит?" потому что 26.10000000001 не равно 26.1. Разница между ними иногда называется ошибкой с плавающей запятой.
Пока мы используем двоичное хранилище с плавающей запятой, ошибка с плавающей запятой будет продолжаться. Это требует, чтобы методы сравнения чисел с плавающей запятой отличались от методов сравнения целых чисел. (то есть для поплавков, не может использовать (x == y) ?
, Быстрая и грязная альтернатива "==" при сравнении чисел с плавающей точкой - сделать что-то вроде этого: if(abs(x-y)<epsilon ){//equal}
где эпсилон - небольшое значение допуска, например 0,000001
Итак, попробуйте что-то вроде этого:
int main(void)
{
double start_value = 26.0;
double end_value = 28.0;
double increment_value = 0.1;
#define EPSILON 0.000001
while(fabs(start_value-end_value)>EPSILON )
{
printf("not equal\n");
start_value += increment_value;
}
printf("equal\n");
getchar();
}
Примечание: выберите значение epsilon, чтобы оно соответствовало окрестности значащих цифр в ваших сравнениях.
Есть много других хороших методов (и многие, кто скажет, что это не один из них), но я использовал этот в течение многих лет, и для моих целей он работал хорошо.
ЗДЕСЬ есть ссылка, немного рассказывающая об этом и других методах.