Из пятой главы книжки Стивена Прата “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 клетке количество зёрнышек на доске сравнялось с годовым урожаем пшеницы в России 🙂
Буду рад вашим комментариям!