В то время как состояние цикла с двойным и плавающим - PullRequest
0 голосов
/ 27 февраля 2019

У меня есть простая задача: «Напишите значение y с помощью следующей формулы для диапазона между xmin и xmax с разностью dx.Единственная проблема, с которой я столкнулся, заключается в том, что при использовании while с плавающей точкой, например, в коде, который я собираюсь предоставить, я получаю на единицу меньше выходных данных y, чем должен был.Для следующего кода

#include <stdio.h>
int main() {
    float x,xmin,xmax,dx,y;
    printf("Input the values of xmin xmax i dx");
    scanf("%f%f%f",&xmin,&xmax,&dx);
    x=xmin;
    while(x<=xmax) {
        y=(x*x-2*x-2)/(x*x+1);
        printf("%.3f   %.3f\n",x,y);
        x=x+dx;
    }
}

для входа (-2 2 0,2) я получаю вывод только до 1,8 (это 20 выходов), а не до 2. Но когда я использую double вместо float всеработает просто отлично (имеет 21 выход).Есть ли что-то, связанное с условием while, о котором я не знаю?

1 Ответ

0 голосов
/ 27 февраля 2019

Это имеет смысл.Float или double - это приближение, а скорее точное представление рациональных чисел a / b: целые числа, b! = 0.Чем ближе вы к 1.000 ... тем лучше приближение, но все же приближение.

Подмножество рациональных чисел, которые гарантированно будут точно представлены представлением с плавающей запятой, являются рациональными: 2 ^ k, с k: целое число [-126 <= x <= 127.Например.const float dx = 0,25f;~ 1 / (2 ^ 2) работало бы нормально.</p>

0,2 не представляется как 0,2, а как: 0.20000000298023223876953125
Следующим ближайшим приближением к 0,2 является: 0,199999988079071044921875
https://www.h -schmidt.net / FloatConverter / IEEE75t.

Альтернативный способ создания циклических операций с плавающей запятой может быть следующим:

#include <stdio.h>
int main() {
    float x,xmin,xmax,dx,y;
    printf("Input the values of xmin xmax i dx");
    scanf("%f%f%f",&xmin,&xmax,&dx);
    x=xmin;

    //expected cummulative error
    const float e = 0.7 * dx;

    do 
    {
        y=(x*x-2*x-2)/(x*x+1);
        printf("%.3f   %.3f\n",x,y);
        x=x+dx;
    }
    while(!(x > (xmax + e)));
}

Представленное выше решение работает, как и ожидалось, но оно будет работать только для небольшого числа итераций..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...