Member 13593396 Ответов: 3

Я столкнулся с проблемой, связанной с циклом while working I этого конкретного вопроса.


#include<conio.h>
#include<stdio.h>         
int main()
{  float x=1.1;
	while(x==1.1)
	{
		printf("%f\n",x);
	    x=x-0.1;
    }   
	getch();
    return 0;
}


Что я уже пробовал:

Я считаю, что выход должен быть 1.1, но у них нет выхода почему????????
когда я выполнил этот код на DEV C++ ......

3 Ответов

Рейтинг:
2

OriginalGriff

Это сложно, но в данном случае речь идет о том, что такое числа на самом деле.
Когда вы вводите "1.1" в качестве числа, что это за число? Мы знаем, что это не целое число - потому что оно имеет дробную составляющую - так что это число с плавающей запятой какой-то формы, но что это за "размер" числа с плавающей запятой? Разве это имеет значение?
В языке Си существует два способа хранения чисел с плавающей запятой: float и double (ну ... технически их три: long double также доступно), и разница заключается в том, что они не занимают много места. float значения обычно занимают 4 байта, а double возьмите 8, потому что они могут содержать более точные значения.

Но что такое 1.1 с точки зрения компилятора? Ответ: это а double потому что это "самый точный", и он получает неявное приведение к float когда вы выполняете задание.
Разве это имеет значение? Да. Поскольку числа с плавающей запятой не хранятся как "один один и точка один также", они хранятся гораздо более сложным способом: Формат с плавающей запятой одинарной точности- Википедия[^] вдается в детали, но поскольку все это бионарное, а не десятичное основание, 1.1 не хранится как "точное" число - это другое. И double версия не такая же, как у float версия, потому что она может хранить больше двоичных цифр.

Простое решение-придерживаться одного формата:

int main()
{
    float x = 1.1;
    while(x == 1.1F)
    {
    printf("%f\n",x);
    x = x - 0.1F;
    } 
    return 0;
}
Или
int main()
{
    double x = 1.1;
    while(x == 1.1)
    {
    printf("%f\n",x);
    x = x - 0.1;
    } 
    return 0;
}
И он будет делать то, что вы ожидаете.


Member 13593396

Сэр здесь в заявлении while(x == 1.1 F) почему u использовал 1.1 F почему мы не можем использовать только 1.1

OriginalGriff

:вздыхать:
Прочтите то, что я сказал выше, и взгляните на ссылку wiki.
1.1 - это двойник, а не поплавок. 1.1 F-это поплавок, а не двойник.

Рейтинг:
2

KarstenK

Мои пре-писатели правы, но и лучшее решение-написать такое
а) код, который позволяет избежать таких проблем с плавающей запятой или
б) используйте какое-то другое сравнение или работайте с константами типа:

//global constant
const double MY_CONSTANT = 1.1;
int main()
{
    double x = 1.1;
    while(x == MY_CONSTANT)
    {
    printf("%f\n",x);
    x = x - 0.1;
    } 
    return 0;
}
в) используйте некоторую определенную разницу для проверки
int main()
{
    double x = 1.1;
    // some diff is accepted
    while( abs(x - MY_CONSTANT) < 0.0000001 )
    {
    printf("%f\n",x);
    x = x - 0.1;
    } 
    return 0;
}
Но всегда используйте более высокую точность типа данных double


Рейтинг:
0

Jochen Arndt

Это происходит потому, что значения с плавающей запятой не являются точными из-за их внутреннего представления. Смотрите эти ссылки:
Руководство По Плавающей Запятой- Что Каждый Программист Должен Знать Об Арифметике С Плавающей Запятой[^]
Что Каждый Компьютерщик Должен Знать Об Арифметике С Плавающей Запятой[^]

В вашем случае это скрыто, Потому что вы сравниваете переменную с плавающей запятой одинарной точности x с константой двойной точности 1.1 Компилятор преобразует вашу переменную float x к double а потом сравните. Потому что 1.1 это одно из тех значений, которые не могут быть представлены точно, сравнение терпит неудачу.

В вашем случае это может сработать при сравнении с одной константой точности (обратите внимание на f постфиксный):

while(x==1.1f)

Но вы не должны полагаться на это. Вместо этого вы должны использовать "сравнение Эпсилона", как описано в разделе Сравнение чисел с плавающей запятой, издание 2012 года | Random ASCII[^].


Jon McKee

Хорошо сказано +1