Не могу понять где ошибка... (Начал изучение C...)

Модератор: Модераторы разделов

Аватара пользователя
murder
Сообщения: 219
ОС: FreeBSD 8.0, Ubuntu 9.10

Не могу понять где ошибка...

Сообщение murder »

Читаю книжку, ну и соответственно делаю те примеры, которые там описаны, и вот на 2-м :) я запнулся, аналог на перле делаю, все ок, а тут чет не пойму. Написано все по книжке

Код: Выделить всё

/* Печать таблицы температур по Фаренгейту и Цельсию */
#include <stdio.h>
main()
{
    int fahr, celsius;
    int lower, upper, step;

    lower = 0;
    upper = 300;
    step = 20;
    fahr = lower;

    while (fahr <= upper) {
        celsius = (5.0/9.0)*(fahr-32.0);
        printf("%3.0f %6.1f\n", fahr, celsius);
        fahr = fahr+step;
    }
}

Ну и вывод:

Код: Выделить всё

murder@mail:~/prog$ cc tepmerature.c
murder@mail:~/prog$ ./a.out
nan    0.0
nan    0.0
  0    0.0
  0    0.0
  0    0.0
  0    0.0
  0    0.0
  0    0.0
  0    0.0
  0    0.0
  0    0.0
  0    0.0
  0    0.0
  0    0.0
  0    0.0
  0    0.0
murder@mail:~/prog$

В чем проблема может быть?
-//- Реальная смерть приходит с косой, а виртуальная с пассатижами -//-
Спасибо сказали:
Аватара пользователя
edoc_modnar
Бывший модератор
Сообщения: 1638
Статус: Форум больше не посещаю

Re: Не могу понять где ошибка...

Сообщение edoc_modnar »

В мозгу :)
celsius = (5.0/9.0)*(fahr-32.0);
Ты в int хочешь запихнуть 5/9 (0), умноженное на что-то еще?
So long, and thanks for all the fish.
Douglas Adams, The Hitchhiker's Guide to the Galaxy
Спасибо сказали:
neuralNetwork
Сообщения: 119
ОС: Debian Squeeze

Re: Не могу понять где ошибка...

Сообщение neuralNetwork »

random_code писал(а):
18.05.2006 06:02
celsius = (5.0/9.0)*(fahr-32.0);
Ты в int хочешь запихнуть 5/9 (0), умноженное на что-то еще?
Не в том дело. (5.0/9.0) - это как раз не ноль в отличие от (5/9). А вот вывод целых чисел как вещественных

Код: Выделить всё

printf("%3.0f %6.1f\n", fahr, celsius);
как раз такой эффект и даёт. Надо писать

Код: Выделить всё

printf("%3d %6d\n", fahr, celsius);
Хотя культурнее, конечно, объявить все переменные вещественными...
Спасибо сказали:
Аватара пользователя
Zm1y
Сообщения: 153
Статус: Steel rat
ОС: Gentoo 2007.0 profile

Re: Не могу понять где ошибка...

Сообщение Zm1y »

neuralNetwork писал(а):
18.05.2006 11:31
random_code писал(а):
18.05.2006 06:02
celsius = (5.0/9.0)*(fahr-32.0);
Ты в int хочешь запихнуть 5/9 (0), умноженное на что-то еще?
Не в том дело. (5.0/9.0) - это как раз не ноль в отличие от (5/9). А вот вывод целых чисел как вещественных

Код: Выделить всё

printf("%3.0f %6.1f\n", fahr, celsius);
как раз такой эффект и даёт. Надо писать

Код: Выделить всё

printf("%3d %6d\n", fahr, celsius);
Хотя культурнее, конечно, объявить все переменные вещественными...


Уважаемый... 5/9 это не ноль... это 4... почитайте хелп по арифметическим операциям и по преобразованию типов в си
work : Sempron 2800/1024/40+120+80+160/NVGFfx6600Gt
Home: 1 2xOpteron x2 3500/4096/4x500SATAII+(2x120+1x80)IDE/NVGFfx7300Gt
2 NoteBook Asus Z99H Gentoo 2007.0 profile
3 NoteBook HP pavillion 6570ea Gentoo 2007.0 profile
Спасибо сказали:
Аватара пользователя
Asgard
Сообщения: 215
Статус: North Valfader

Re: Не могу понять где ошибка...

Сообщение Asgard »

5/9 это не ноль... это 4

уважаемый, вы несёте бред. полнейший
sator arepo tenet opera rotas ;)
------------------------------------------------------------
LJ
Спасибо сказали:
Аватара пользователя
powerfox
Сообщения: 458

Re: Не могу понять где ошибка...

Сообщение powerfox »

(Asgard @ May 18 2006, в 15:09) писал(а):Уважаемый... 5/9 это не ноль... это 4... почитайте хелп по арифметическим операциям и по преобразованию типов в си


Это 0.5555555555555, в int это должно быть 1.
Спасибо сказали:
Аватара пользователя
Asgard
Сообщения: 215
Статус: North Valfader

Re: Не могу понять где ошибка...

Сообщение Asgard »

powerfox писал(а):
18.05.2006 15:45
(Asgard @ May 18 2006, в 15:09) писал(а):
Уважаемый... 5/9 это не ноль... это 4... почитайте хелп по арифметическим операциям и по преобразованию типов в си


Это 0.5555555555555, в int это должно быть 1.


а если на практике проверить?

Код: Выделить всё

#include <stdio.h>

int main()
{
        int i = 5 / 9;
        printf("%d\n", i);
        return 0;
}


результат - 0.
sator arepo tenet opera rotas ;)
------------------------------------------------------------
LJ
Спасибо сказали:
Аватара пользователя
Zm1y
Сообщения: 153
Статус: Steel rat
ОС: Gentoo 2007.0 profile

Re: Не могу понять где ошибка...

Сообщение Zm1y »

Asgard писал(а):
18.05.2006 15:50
powerfox писал(а):
18.05.2006 15:45

(Asgard @ May 18 2006, в 15:09) писал(а):
Уважаемый... 5/9 это не ноль... это 4... почитайте хелп по арифметическим операциям и по преобразованию типов в си


Это 0.5555555555555, в int это должно быть 1.


а если на практике проверить?

Код: Выделить всё

#include <stdio.h>

int main()
{
        int i = 5 / 9;
        printf("%d\n", i);
        return 0;
}


результат - 0.


Звиняюсь... не увидел что 5/9 /*почему то показалось что 9/5 и это 1*/
Посыпаю голову пеплом...
work : Sempron 2800/1024/40+120+80+160/NVGFfx6600Gt
Home: 1 2xOpteron x2 3500/4096/4x500SATAII+(2x120+1x80)IDE/NVGFfx7300Gt
2 NoteBook Asus Z99H Gentoo 2007.0 profile
3 NoteBook HP pavillion 6570ea Gentoo 2007.0 profile
Спасибо сказали:
Аватара пользователя
edoc_modnar
Бывший модератор
Сообщения: 1638
Статус: Форум больше не посещаю

Re: Не могу понять где ошибка...

Сообщение edoc_modnar »

neuralNetwork писал(а):
18.05.2006 11:31
random_code писал(а):
18.05.2006 06:02
celsius = (5.0/9.0)*(fahr-32.0);
Ты в int хочешь запихнуть 5/9 (0), умноженное на что-то еще?
Не в том дело. (5.0/9.0) - это как раз не ноль в отличие от (5/9).

Да какая разница, 5/9 или 5.0/9.0, если все остальное в выражении -- int'ы и присваивается оно int'овой переменной?
So long, and thanks for all the fish.
Douglas Adams, The Hitchhiker's Guide to the Galaxy
Спасибо сказали:
Аватара пользователя
powerfox
Сообщения: 458

Re: Не могу понять где ошибка...

Сообщение powerfox »

Ошибся.
Спасибо сказали:
Аватара пользователя
murder
Сообщения: 219
ОС: FreeBSD 8.0, Ubuntu 9.10

Re: Не могу понять где ошибка...

Сообщение murder »

Всем спасибо, особенно neuralNetwork, т.к. указал где ошибка :)
neuralNetwork писал(а):
18.05.2006 11:31
Хотя культурнее, конечно, объявить все переменные вещественными...

Я ведь только начинаю, в книжке так написано :)
-//- Реальная смерть приходит с косой, а виртуальная с пассатижами -//-
Спасибо сказали:
Аватара пользователя
aLexx programmer
Сообщения: 985
Статус: Турук-Макто
ОС: Gentoo -> Ubuntu

Re: Не могу понять где ошибка...

Сообщение aLexx programmer »

(murder @ May 18 2006, в 18:08) писал(а):Я ведь только начинаю, в книжке так написано

Что за книжка такая?
Спасибо сказали:
neuralNetwork
Сообщения: 119
ОС: Debian Squeeze

Re: Не могу понять где ошибка...

Сообщение neuralNetwork »

random_code писал(а):
18.05.2006 16:59
Да какая разница, 5/9 или 5.0/9.0, если все остальное в выражении -- int'ы и присваивается оно int'овой переменной?
Разница очень существенная. Если писать 5/9, то результат - 0 имеет тип int и результат всего выражения - 0. Если писать 5.0/9.0, то результат 0.555555555 типа double и к этому типу будут приведены все остальные операнды, а приведение к int будет осуществляться лишь при присваивании. Ответ будет правильный, но без дробной части.
murder Пожалуйста. Успехов в Ваших начинаниях! :)
Спасибо сказали:
Аватара пользователя
edoc_modnar
Бывший модератор
Сообщения: 1638
Статус: Форум больше не посещаю

Re: Не могу понять где ошибка...

Сообщение edoc_modnar »

neuralNetwork писал(а):
18.05.2006 20:58
random_code писал(а):
18.05.2006 16:59
Да какая разница, 5/9 или 5.0/9.0, если все остальное в выражении -- int'ы и присваивается оно int'овой переменной?
Разница очень существенная. Если писать 5/9, то результат - 0 имеет тип int и результат всего выражения - 0. Если писать 5.0/9.0, то результат 0.555555555 типа double и к этому типу будут приведены все остальные операнды, а приведение к int будет осуществляться лишь при присваивании. Ответ будет правильный, но без дробной части.

Так точно. Только тут еще многое зависит от компилятора, в каком порядке и к чему приводить.
/me иногда сильно удивляется, какую лажу иногда выводят MSVC.NET в универе :).

aLexx programmer писал(а):
18.05.2006 19:04
(murder @ May 18 2006, в 18:08) писал(а):
Я ведь только начинаю, в книжке так написано

Что за книжка такая?

Здрассте. Керниган-Ритчи. Классика, тысызыть.
So long, and thanks for all the fish.
Douglas Adams, The Hitchhiker's Guide to the Galaxy
Спасибо сказали:
Аватара пользователя
murder
Сообщения: 219
ОС: FreeBSD 8.0, Ubuntu 9.10

Re: Не могу понять где ошибка...

Сообщение murder »

random_code писал(а):
18.05.2006 21:05
Здрассте. Керниган-Ритчи. Классика, тысызыть.

Она самая :)
Но только вот вопрос, в книжке то врятли ошибутся или просто то что там написано частично устарело?
-//- Реальная смерть приходит с косой, а виртуальная с пассатижами -//-
Спасибо сказали:
Аватара пользователя
aLexx programmer
Сообщения: 985
Статус: Турук-Макто
ОС: Gentoo -> Ubuntu

Re: Не могу понять где ошибка...

Сообщение aLexx programmer »

(murder @ May 19 2006, в 14:56) писал(а):Она самая
Но только вот вопрос, в книжке то врятли ошибутся или просто то что там написано частично устарело?

У Вас книжка, похоже, неправильная :)

В Кернигане-Ритчи вычисление идёт так:

Код: Выделить всё

celsius = 5 * (fahr - 32) / 9;

murder , сравните со своим кодом и найдите 10 отличий :)

random_code, я потому и спросил про книгу, что там другой код.
Наверное, у автора темы раннее издание.
Спасибо сказали:
Аватара пользователя
GRS
Сообщения: 236
Статус: C++ Pro
ОС: Suse10.2/XP

Re: Не могу понять где ошибка...

Сообщение GRS »

Она самая smile.gif
Но только вот вопрос, в книжке то врятли ошибутся или просто то что там написано частично устарело?

Книга мягко говоря ... даже эквивалентов нет.
Для начинающих самые лучшие книги у Дейтлов серия Учимся программировать на <язык программирования>.
Спасибо сказали:
Nark
Сообщения: 21

Re: Не могу понять где ошибка...

Сообщение Nark »

Я сам только начал изучать С.
В качестве учебника выбрал тоже Керниган-Ритчи (Мне нравится :) )!
Вот как раз этот пример разбирается на http://www.intuit.ru/department/pl/cpl/1/2.html

По поводу деления 5/9 и 5.0/9.0 там говорится:
причина использования выражения 5.0/9.0 вместо выглядящего проще 5/9 заключается в том, что в языке "C", как и во многих других языках, при делении целых происходит усечение, состоящее в отбрасывании дробной части результата. Таким образом, результат операции 5/9 равен нулю, и, конечно, в этом случае все температуры оказались бы равными нулю. Десятичная точка в константе указывает, что она имеет тип с плавающей точкой, так что, как мы и хотели, 5.0/9.0 равно 0.5555....

Мы также писали 32.0 вместо 32, несмотря на то, что так как переменная fahr имеет тип float, целое 32 автоматически бы преобразовалось к типу float (в 32.0) перед вычитанием. С точки зрения стиля разумно писать плавающие константы с явной десятичной точкой даже тогда, когда они имеют целые значения; это подчеркивает их плавающую природу для просматривающего программу и обеспечивает то, что компилятор будет смотреть на вещи так же, как и Вы.


Код примера:

Код: Выделить всё

/* print fahrenheit-celsius table
for f = 0, 20, ..., 300 */
main()
{
int lower, upper, step;
float fahr, celsius;
lower = 0;  /* lower limit of temperature
table */
upper =300; /* upper limit */
step  = 20; /* step size */
fahr = lower;
while (fahr <= upper) {
  celsius = (5.0/9.0) * (fahr -32.0);
  printf("%4.0f %6.1f\n", fahr, celsius);
  fahr = fahr + step;
}
}


Я делал - у меня все получалось.
Я думаю, что ошибка у murder'а здесь:

Код: Выделить всё

int lower, upper, step;
int fahr, celsius;

А нужно:

Код: Выделить всё

int lower, upper, step;
float fahr, celsius;

Ведь в

Код: Выделить всё

printf("%4.0f %6.1f\n", fahr, celsius);
fahr и celsius выводится как вещественное,
а в

Код: Выделить всё

celsius = (5.0/9.0) * (fahr -32.0);
celsius может быть только вещественным.
Если я не прав, то буду признателен, если мне объяснят в чем .
Спасибо сказали:
Аватара пользователя
aLexx programmer
Сообщения: 985
Статус: Турук-Макто
ОС: Gentoo -> Ubuntu

Re: Не могу понять где ошибка...

Сообщение aLexx programmer »

Nark писал(а):
18.08.2006 10:31

Код: Выделить всё

celsius = (5.0/9.0) * (fahr -32.0);
celsius может быть только вещественным.
Если я не прав, то буду признателен, если мне объяснят в чем .

Не обязательно.
Например, если ты сделаешь

Код: Выделить всё

 int qqq = 3.0/2.0;

то сначала вычислится правая часть (1.5), оперируя типом double, и только потом, при присваивании, результат будет преобразван к типу левого операнда, т.е., к типу int (отброс дробной части: 1.5 -> 1).
Спасибо сказали:
v04bvs
Сообщения: 636
ОС: Debian GNU/Linux

Re: Не могу понять где ошибка...

Сообщение v04bvs »

Ведь в

Код: Выделить всё

printf("%4.0f %6.1f\n", fahr, celsius);
fahr и celsius выводится как вещественное,
а в

Код: Выделить всё

celsius = (5.0/9.0) * (fahr -32.0);
celsius может быть только вещественным.
Если я не прав, то буду признателен, если мне объяснят в чем .

дело в том, что когда функция printf видит спецификатор формата %f, она считает, что переменная имеет тип float, но на самом деле передаётся int, поэтому получается неразбериха. На самом деле возможно даже аварийное завершение программы из за такой мелочи. Думаю, когда вы будете читать про функции с переменным числом параметров, вы в этом лучше разберётесь, сейчас просто старайтесь быть внимательными и компилируйте с флагом -Wall

Для того, чтобы лучше понять то, о чём я говорю, поэкспериментируйте с такой программой:
#include <stdio.h>

int main()
{
int a = 7;
printf("%f\n", a);
printf("%d\n", a);
return 0;
}
Спасибо сказали: