пятница, 27 декабря 2013 г.

Переменные и арифметические выражения

fahr.c

#include <stdio.h>

/* print Fahrenheit-Celsius table
 * for fahr = 0, 20, ..., 300 */

int main(void)
{
        int fahr, celsius;
        int lower, upper, step;

        lower = 0;      /* lower limit of temperature scale */
        upper = 300;    /* upper limit */
        step = 20;      /* step size */

        fahr = lower;
        while (fahr <= upper) {
                celsius = 5 * (fahr - 32) / 9;
                printf("%d\t%d\n", fahr, celsius);
                fahr = fahr + step;
        }

        return 0;
}

$ cc -g -O0 -Wall -o a.out fahr.c
 $ ./a.out

0       -17
20      -6
40      4
60      15
80      26
100     37
120     48
140     60
160     71
180     82
200     93
220     104
240     115
260     126
280     137
300     148

Причина, по которой мы сначала умножаем на 5 и затем делим на 9, а не сразу умножаем на 5/9, связана с тем, что в Си деление целых сопровождается отбрасыванием, т. е. потерей дробной части. Так как 5 и 9 - целые, отбрасывание в 5/9 дало бы нуль, и на месте температур по Цельсию были бы напечатаны нули.

#include <stdio.h>

/* print Fahrenheit-Celsius table
 * for fahr = 0, 20, ..., 300 */

int main(void)
{
        int fahr, celsius;
        int lower, upper, step;

        lower = 0;      /* lower limit of temperature scale */
        upper = 300;    /* upper limit */
        step = 20;      /* step size */

        fahr = lower;
        while (fahr <= upper) {
                celsius = 5 / * (fahr - 32);
                printf("%d\t%d\n", fahr, celsius);
                fahr = fahr + step;
        }

        return 0;
}


$ cc -g -O0 -Wall -o a.out fahr.c
$ ./a.out
0       0
20      0
40      0
60      0
80      0
100     0
120     0
140     0
160     0
180     0
200     0
220     0
240     0
260     0
280     0
300     0



Существуют еще две проблемы, связанные с программой преобразования температур. Одна из них (более простая) состоит в том, что выводимый результат выглядит несколько неряшливо, поскольку числа не выровнены по правой позиции колонок. Это легко исправить, добавив в каждый из спецификаторов формата %d указание о ширине поля; при этом программа будет печатать числа, прижимая их к правому краю указанных полей. Например, мы можем написать
чтобы в каждой строке первое число печатать в поле из трех позиций, а второе - из шести.

#include <stdio.h>

/* print Fahrenheit-Celsius table
 * for fahr = 0, 20, ..., 300 */

int main(void)
{
        int fahr, celsius;
        int lower, upper, step;

        lower = 0;      /* lower limit of temperature scale */
        upper = 300;    /* upper limit */
        step = 20;      /* step size */

        fahr = lower;
        while (fahr <= upper) {
                celsius = 5 * (fahr - 32) / 9;
                printf("%3d\t%6d\n", fahr, celsius);
                fahr = fahr + step;
        }

        return 0;
}


$ cc -g -O0 -Wall -o a.out fahr.c
$ ./a.out
  0        -17
 20         -6
 40          4
 60         15
 80         26
100         37
120         48
140         60
160         71
180         82
200         93
220        104
240        115
260        126
280        137
300        148

Вторая, более серьезная проблема связана с тем, что мы пользуемся целочисленной арифметикой и поэтому не совсем точно вычисляем температуры по шкале Цельсия. Например, 0°F на самом деле (с точностью до десятой) равно -17.8 °С, а не -17. Чтобы получить более точные значения температур, нам надо пользоваться не целочисленной арифметикой, а арифметикой с плавающей точкой. Это потребует некоторых изменений в программе.

fahr2.c

#include <stdio.h>

/* print Fahrenheit-Celsius table
 * for fahr = 0, 20, ..., 300; floating-point version */

int main(void)
{
        float fahr, celsius;
        int lower, upper, step;

        lower = 0;      /* lower limit of temperatuire scale */
        upper = 300;    /* upper limit */
        step = 20;      /* step size */

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

        return 0;
}

$ cc -g -O0 -Wall -o a.out fahr2.c
$ ./a.out
  0  -17.8
 20   -6.7
 40    4.4
 60   15.6
 80   26.7
100   37.8
120   48.9
140   60.0
160   71.1
180   82.2
200   93.3
220  104.4
240  115.6
260  126.7
280  137.8
300  148.9

Комментариев нет:

Отправить комментарий