[Язык C] Программа про зернышки на шахматной доске (глава 5)

Из пятой главы книжки Стивена Прата “C Primer Plus” – программа по мотивам известной присказки, которая иллюстрирует возрастание по экспоненте.

Предыстория:
Царь предложил выбрать награду герою за услугу; герой попросил положить на шахматную доску одно зернышко на первую клетку, два зернышка на вторую, четыре – на третью и удваивать зернышки таким образом, пока доска не заполнится. Царь был поражен скромностью и согласился.. Что из этого вышло:

Моя первая версия программы уперлась в ограничение int на 32 клетке:

#include <stdio.h>
int main (void)
{
const int chess_board = 64;
int square = 1;
double grains = 1.0, grains_sum = 1.0;
const float grain_world_tons = 7.0e7; // yield of wheat in Russia per year in tons
const float grain_mass = 6.5e-8; // how much tons in one grain
float rus_yield = grain_world_tons / grain_mass;
float propotion_of_rus_yield = 1.0 / rus_yield;
printf("Russian yield of wheat (in number or grains): %.1e.\n\nNow lets take a look at chess board:\n",rus_yield);
printf("Square # | Grains | Total grains | Part from Russian yield \n");
while (square<65)
{
printf("%d %.2e %.2e %.2e\n",square, grains, grains_sum,propotion_of_rus_yield);
grains = grains * 2;
square = square + 1;
grains_sum = grains_sum + grains;
propotion_of_rus_yield = grains_sum/rus_yield;
}
getchar();
return 0;
}

Сделаем вывод в экспоненциальной форме и переназначим тип переменной с int на double. Также сравним это с урожаем пшеницы в России:

#include <stdio.h>
int main (void)
{
const int chess_board = 64;
int square = 1;
double grains = 1, grains_sum = 1;
const float grain_world_tons = 7.0e7; // yield of wheat in Russia per year in tons
const float grain_mass = 6.5e-8; // how much tons in one grain
float rus_yield = grain_world_tons / grain_mass;
float propotion_of_rus_yield = 1 / rus_yield;
printf("Russian yield of wheat (in number or grains): %.1e.\n\nNow lets take a look at chess board:\n",rus_yield);
printf("Square # | Grains | Total grains | Part from Russian yield \n");
while (square<65)
{
printf("%d %.2e %.2e %.2e\n",square, grains, grains_sum,propotion_of_rus_yield);
grains = grains * 2;
square = square + 1;
grains_sum = grains_sum + grains;
propotion_of_rus_yield = grains_sum/rus_yield;
}
getchar();
return 0;
}

Программа вышла не такая как в листинге книжки, пришлось напихать туда пересчет тонн на зёрнышки, т.к. интересовали цифры нашего урожая 🙂 Ну и надо приучаться использовать константы в #define, чтобы легче все читалось, т.к. переменных тут и так дофига. Также программе был косяк с тем, что приходится сравнивать в цикле не с константой 64, а с числом 65, иначе первого зернышка на первой клетке не будет в цикле; это решается выводом печати первого зернышка в отдельной строке, вот так:

#include <stdio.h>
#define CHESS_BOARD 64
int main (void)
{
int square = 1;
double grains = 1.0, grains_sum = 1.0;
const float grain_world_tons = 7.0e7; // yield of wheat in Russia per year in tons
const float grain_mass = 6.5e-8; // how much tons in one grain
float rus_yield = grain_world_tons / grain_mass;
float propotion_of_rus_yield = 1.0 / rus_yield;
printf("Russian yield of wheat (in number or grains): %.1e.\n\nNow lets take a look at chess board:\n",rus_yield);
printf("Square # | Grains | Total grains | Part from Russian yield \n");
printf("%d %.2e %.2e %.2e\n",square, grains, grains_sum,propotion_of_rus_yield); // printing first grain
while (square<CHESS_BOARD)
{
square = square + 1;
grains = grains * 2;
grains_sum = grains_sum + grains;
propotion_of_rus_yield = grains_sum/rus_yield;
printf("%d %.2e %.2e %.2e\n",square, grains, grains_sum,propotion_of_rus_yield);
}
getchar();
return 0;
}

В итоге мы получим:

Russian yield of wheat (in number or grains): 1.1e+15.

Now lets take a look at chess board:
Square # | Grains | Total grains | Part from Russian yield 
1         1.00e+00     1.00e+00       9.29e-16
2         2.00e+00     3.00e+00       2.79e-15
3         4.00e+00     7.00e+00       6.50e-15
4         8.00e+00     1.50e+01       1.39e-14
5         1.60e+01     3.10e+01       2.88e-14
6         3.20e+01     6.30e+01       5.85e-14
7         6.40e+01     1.27e+02       1.18e-13
8         1.28e+02     2.55e+02       2.37e-13
9         2.56e+02     5.11e+02       4.74e-13
10         5.12e+02     1.02e+03       9.50e-13
11         1.02e+03     2.05e+03       1.90e-12
12         2.05e+03     4.10e+03       3.80e-12
13         4.10e+03     8.19e+03       7.61e-12
14         8.19e+03     1.64e+04       1.52e-11
15         1.64e+04     3.28e+04       3.04e-11
16         3.28e+04     6.55e+04       6.09e-11
17         6.55e+04     1.31e+05       1.22e-10
18         1.31e+05     2.62e+05       2.43e-10
19         2.62e+05     5.24e+05       4.87e-10
20         5.24e+05     1.05e+06       9.74e-10
21         1.05e+06     2.10e+06       1.95e-09
22         2.10e+06     4.19e+06       3.89e-09
23         4.19e+06     8.39e+06       7.79e-09
24         8.39e+06     1.68e+07       1.56e-08
25         1.68e+07     3.36e+07       3.12e-08
26         3.36e+07     6.71e+07       6.23e-08
27         6.71e+07     1.34e+08       1.25e-07
28         1.34e+08     2.68e+08       2.49e-07
29         2.68e+08     5.37e+08       4.99e-07
30         5.37e+08     1.07e+09       9.97e-07
31         1.07e+09     2.15e+09       1.99e-06
32         2.15e+09     4.29e+09       3.99e-06
33         4.29e+09     8.59e+09       7.98e-06
34         8.59e+09     1.72e+10       1.60e-05
35         1.72e+10     3.44e+10       3.19e-05
36         3.44e+10     6.87e+10       6.38e-05
37         6.87e+10     1.37e+11       1.28e-04
38         1.37e+11     2.75e+11       2.55e-04
39         2.75e+11     5.50e+11       5.10e-04
40         5.50e+11     1.10e+12       1.02e-03
41         1.10e+12     2.20e+12       2.04e-03
42         2.20e+12     4.40e+12       4.08e-03
43         4.40e+12     8.80e+12       8.17e-03
44         8.80e+12     1.76e+13       1.63e-02
45         1.76e+13     3.52e+13       3.27e-02
46         3.52e+13     7.04e+13       6.53e-02
47         7.04e+13     1.41e+14       1.31e-01
48         1.41e+14     2.81e+14       2.61e-01
49         2.81e+14     5.63e+14       5.23e-01
50         5.63e+14     1.13e+15       1.05e+00
51         1.13e+15     2.25e+15       2.09e+00
52         2.25e+15     4.50e+15       4.18e+00
53         4.50e+15     9.01e+15       8.36e+00
54         9.01e+15     1.80e+16       1.67e+01
55         1.80e+16     3.60e+16       3.35e+01
56         3.60e+16     7.21e+16       6.69e+01
57         7.21e+16     1.44e+17       1.34e+02
58         1.44e+17     2.88e+17       2.68e+02
59         2.88e+17     5.76e+17       5.35e+02
60         5.76e+17     1.15e+18       1.07e+03
61         1.15e+18     2.31e+18       2.14e+03
62         2.31e+18     4.61e+18       4.28e+03
63         4.61e+18     9.22e+18       8.56e+03
64         9.22e+18     1.84e+19       1.71e+04

Итого, на 50 клетке количество зёрнышек на доске сравнялось с годовым урожаем пшеницы в России 🙂

Буду рад вашим комментариям!

This entry was posted in С (Си). Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *