Почему double, long double всегда показывают 0 в качестве вывода?

Я пишу код, чтобы найти расстояние точки (25,40000) от фиксированной точки (47,132000). Расстояние всегда печатается равным 0,0000. Я пробовал проверять другие комбинации, задавая меньшие значения точек и печатая их с помощью %d, все отлично работает. А вот с %ld,%lf,%Lf что-то не в порядке. Пожалуйста, помогите.

#include<stdio.h>
#include<math.h>

int main()
{
   int x=25,y=40000;  
   //printf("Enter x,y");
   //scanf(%d %d,&x,&y) 
   long double dist;
   dist=sqrt((47-x)*(47-x)+(132000-y)*(132000-y));   
   printf(" x= %d y=%d dist=%Lf\n",x,y,dist);
   return 0;
}

person Apoorva Jain    schedule 03.06.2020    source источник
comment
Измените тип int переменных с int на тип long long int.   -  person Vlad from Moscow    schedule 03.06.2020
comment
Вы смотрели на значение, фактически переданное sqrt? Я не удивлюсь, если это не то, что вы ожидаете.   -  person Thomas Jager    schedule 03.06.2020
comment
у вас много опечаток, вы должны позаботиться об этом.   -  person snatchysquid    schedule 03.06.2020
comment
БОЛЬШОЙ плюс за комментирование ввода и замену его жестко закодированными значениями. Это действительно хорошо.   -  person klutt    schedule 03.06.2020
comment
@snatchysquid Я вижу только dust->dist (помимо отсутствующих включений)   -  person Thomas Jager    schedule 03.06.2020
comment
Но да, скопируйте код из вашего редактора, чтобы убедиться, что он компилируется. Создайте минимально воспроизводимый пример   -  person klutt    schedule 03.06.2020
comment
Скопируйте/вставьте свой точный код, минимально воспроизводимый пример, самый короткий полный код, показывающий проблему. Не то, что вы думаете, может быть то же самое.   -  person Weather Vane    schedule 03.06.2020
comment
@Apoorva Jain Зачем менять вопрос после хорошего ответа? Теперь вопрос больше не имеет смысла с ответом. Рекомендую откатить вашу правку.   -  person chux - Reinstate Monica    schedule 03.06.2020
comment
@chux-ReinstateMonica, да, я понял вашу точку зрения, но цель этого была в том, что в тот момент я не знал, что код будет работать нормально, поскольку он давал тот же неправильный ответ. Теперь кажется, что это была ошибка компилятора, и использование double вместо long double работает отлично.   -  person Apoorva Jain    schedule 03.06.2020
comment
@ApoorvaJain Хорошо, но зачем принимать ответ, который не отвечает на вопрос long double/double?   -  person chux - Reinstate Monica    schedule 04.06.2020
comment
Если вы используете gcc для Windows, есть некоторые проблемы с long double, см. здесь   -  person M.M    schedule 04.06.2020
comment
Кстати, sqrt(3) — это функция, для которой требуется параметр double, а вы передаете выражение, полное целочисленных значений. Компилятор выполняет автоматическое преобразование в double, но если бы у вас было какое-то деление, вы бы получили еще один сюрприз при целочисленном делении. Если вы работаете с числами с плавающей запятой, используйте литералы с плавающей запятой (10000 — целочисленный литерал, а 10000.0double литерал с плавающей запятой)   -  person Luis Colorado    schedule 05.06.2020


Ответы (1)


В вашем коде происходит целочисленное переполнение. Код ниже работает -

int main()
{
   long long int x=25,y=40000;       //int was overflowing and causing you error
   long double dist;
   dist=sqrt((47-x)*(47-x)+(132000-y)*(132000-y));   //this will safely compute within range and return the desired result
   printf("After distance\n");
   printf(" x= %lld y=%lld dist=%Lf\n",x,y,dist);
   return 0;
}

Вы получали неправильный вывод (-nan, когда я пробовал), потому что значение выражения внутри sqrt() переполнялось и становилось отрицательным. (132000-y)*(132000-y) не помещается в целочисленный диапазон и дает отрицательное значение. Поскольку отрицательный квадратный корень не определен, sqrt() возвращает nan в качестве результата. Изменение типа y на long long int устранит ошибку.

Надеюсь это поможет !

person Abhishek Bhagate    schedule 03.06.2020
comment
Возможно, вы захотите дать более подробное объяснение того, что происходит. Хотя верно то, что 16-битный int не может вместить 40000, это только его часть. Умножение, включающее y, также может привести к переполнению 32-битного int. На большинстве современных платформ это, вероятно, проблема. - person Thomas Jager; 03.06.2020
comment
@ThomasJager Я добавил правильное объяснение. Посмотрите, правильно ли это, и скажите, если я что-то пропустил. - person Abhishek Bhagate; 03.06.2020
comment
(Я закончил писать незадолго до последнего редактирования) Ваш отредактированный ответ не совсем правильный. Если бы единственная проблема заключалась в том, что y было отрицательным, тот факт, что оно вычитается из другого числа, гарантировал бы передачу положительного результата в sqrt. Независимо от исходного значения int y, (132000-y) является 32-битным целым числом (на обычных платформах). Этот результат переполнится, что приведет к UB. Вот почему просто использовать long int для x и y недостаточно, так как вам гарантирован только диапазон [−2 147 483 647, +2 147 483 647]. Хотя это может легко вместить 40000, этого недостаточно для мульта. - person Thomas Jager; 03.06.2020
comment
long long int может содержать значения до 9223372036854775807 . Переполнение происходит не потому, что 40000 не помещается в y, а потому, что оно не может содержать произведение (132000-y)*(132000-y). Сделать это long long int было бы достаточно, чтобы сохранить значение. Таким образом, это работает в большинстве случаев, если только вы не готовы работать за пределами диапазона 9223372036854775807 , где вам придется реализовывать большие целые числа. - person Abhishek Bhagate; 03.06.2020
comment
@Abhishek Предоставленный вами отредактированный код также показывает тот же результат 0,0000. - person Apoorva Jain; 03.06.2020
comment
@ApoorvaJain отлично работает в моей среде IDE. Проверьте также здесь — ide.geeksforgeeks.org/GqdtuWkUgm - person Abhishek Bhagate; 03.06.2020
comment
@Abhishek, да, я проверил. Благодарю вас. Он отлично работает в GeeksForGeeks IDE, но не на моем Dev C++ 5.11. - person Apoorva Jain; 03.06.2020
comment
@ApoorvaJain Просто попробуйте назначить что-то вроде dist=1.2; и проверьте, печатает ли он по-прежнему 0. - person Abhishek Bhagate; 03.06.2020
comment
@Abhishek Я пытался присвоить значения, но это не сработало лучше, это было то же самое 0,0000, но при изменении long double на double и %Lf на %lf это дало правильный результат. - person Apoorva Jain; 03.06.2020
comment
Да, это, вероятно, связано с проблемой компилятора, и использование double, вероятно, сделает вашу работу. Проверьте это - bytes.com/topic/c/answers/. stackoverflow.com/questions/4089174/printf-and-long-double< /а>. Переключение на другую IDE/изменение компилятора позволит вам использовать long double - person Abhishek Bhagate; 03.06.2020
comment
long double здесь не используется в коде, так как sqrt() принимает и возвращает double. Используйте double list;. - person chux - Reinstate Monica; 03.06.2020
comment
@chux-Восстановить Монику правильно! вы должны использовать sqrtl(), если хотите получить long double - person Abhishek Bhagate; 04.06.2020