Все права на текст принадлежат автору: Дмитрий Витальевич Елисеев.
Это короткий фрагмент для ознакомления с книгой.
Рассказы о математике с примерами на языках Python и CДмитрий Витальевич Елисеев

Елисеев Д.


Рассказы о математике с примерами на языках Python и C



Версия текста 1.6. (с) 2018


Введение

Как сказал еще Галилей, “Книга природы написана на языке математики”, и с этим сложно не согласиться. Математика это универсальный язык науки, это базовые принципы, на которых построена вся Вселенная. 2+2=4 независимо от того, верим мы в это или нет, знаем мы это или нет, существуем мы вообще или нет, и это будет верно не только для нас, но и для жителя Альфы Центавра.


Из этого следует важное правило: математические законы нельзя придумать, их можно только открыть. Треугольник подчинялся теореме Пифагора еще до того, как Пифагор открыл и сформулировал известную теорему. Число Пи было вычислено в древнем Китае, но его значение было таким всегда - еще до того как появился не только Китай, но и наша планета Земля.


Именно поэтому я надеюсь, что кто-то из читателей с помощью этой книги откроет для себя в математике что-то новое. Увы, в представлении большинства, математика - это достаточно скучная наука, вероятно так ее преподают в школе. Если кто-то с помощью этой книги найдет для себя что-то новое, можно считать что время было потрачено не зря.


Эта книга не задачник, а скорее сборник рассказов о тех или иных математических вопросах. Т.к. математические примеры без цифр бессмысленны, “практическая” часть дается на языках программирования Python и Си.


Номер версии в заголовке указан неслучайно. Эта книга не закончена, и по мере появления каких-то новых интересных вопросов она будет дополняться. Желающие также могут присылать свои истории или задачи по адресу dmitryelj@gmail.com, наиболее интересные из них будут включены в текст. Обо найденных неточностях также просьба писать на этот адрес.


Книга распространяется бесплатно в электронном виде, в различных форматах (PDF, FB2) ее можно скачать по ссылке https://cloud.mail.ru/public/4SGE/oE2EGEWnp. Там же доступен и архив с примерами программ.


Приятного чтения.


Елисеев Дмитрий


История версий текста


04.2017 - 1.0


09.2017 - 1.1, 1.2 - добавлены главы 19 и 20 про нейронные сети


11.2017 - 1.3, добавлена глава 21 про фракталы


11.2017 - 1.4, дополнена глава 7 про магические квадраты, добавлены главы 22 и 23 про “горн Гавриила” и построение графиков функций, в “Приложения” добавлен пример оптимизации кода на Python.


12.2017 - 1.5, дополнена глава 4 про шарообразность Земли.


01.2016 - 1.6, добавлена глава 24 про точность компьютерных вычислений, глава 25 про календарь, добавлено Приложение 4.

1. Основы языков Python и Си

Математика немыслима без расчетов и примеров вычислений. Примеры в данной книге иллюстрируются фрагментами кода на языке Python. Этот язык удобен тем, что он очень прост и подходит для начинающих, поэтому кратко рассмотрим как им пользоваться.


Для использования языка Python нужно установить интерпретатор языка с сайта https://www.python.org/downloads/ или воспользоваться онлайн-версией, например на странице https://repl.it/languages/python3. Все примеры из книги тестировались на Python версии 2.7.


Для запуска Python-программы необходимо:

Сохранить файл в Блокноте с любым именем и расширением .py, например test1.py.

Открыть консоль (нажать Win+R и набрать cmd), в консоли набрать команду (без кавычек) “python путь_к_файлу.py”, например “python C:\PythonApps\test1.py”.

Как более удобный вариант, можно скачать бесплатную среду разработки PyСharm community edition, и редактировать и запускать файлы в ней. Скачать PyСharm можно со страницы https://www.jetbrains.com/pycharm/download/.


Кстати, чтобы запустить короткую программу на Python, ее необязательно сохранять в файл, код можно ввести непосредственно в интерпретатор. Для этого достаточно запустить (Win+R) программу python.exe и просто ввести подряд соответствующие строки:


Для запуска программы на языке Си, ее сначала надо сохранить файле с расширением .c, и выполнить команду “gcc имя_файла.c”. Будет создан exe-файл, который можно запустить. Бесплатный компилятор С/C++ можно установить с помощью утилиты mingw-get, скачать которую можно на странице https://sourceforge.net/projects/mingw/files/. Также можно воспользоваться и любой онлайн-версией c++ компилятора, например этой.


Минимальная программа на Си выглядит так:

#include <stdio.h>


int main()

{

printf("Hello world\n");

return 0;

}


Рассмотрим простые примеры использования.


Объявление и вывод переменных

Python: достаточно ввести имя и значение.

x = 3

y = 10

print("x=", x)

print(x+y)


В отличие от языка С++, тип переменной будет определен автоматически, указывать его не нужно. Его можно при необходимости узнать, введя print (type(x)).


: необходимо явно указать тип и значение переменной.

int x = 3;

int y = 10;

printf("x=%d\n", x);

printf("%d\n", x+y);


Циклы

В отличие от того же С++ или Java, циклы в Python задаются отступами, что после других языков программирования может быть непривычным. Часть кода, находящаяся внутри цикла, будет выполнена заданное количество раз.


Python

Вывод чисел от 1 до 9:

for p in range(1,10):

print (p)


Для сравнения, вот такой код без отступов работать не будет, и это важно помнить, например при копировании кода из этой книги:

for p in range(1,10):

print (p)

Вывод чисел от 1 до 9 с шагом 2:

for p in range(1,10,2):

print (p)


Кстати, в Python 2.7 функция range возвращает объект “список”, и соответственно выделяет память заданного размера. Для большинства примеров в книге это не критично, но если нужно написать код типа for p in range(1,10000000), то range следует заменить на xrange, в противном случае программа вполне может занять гигабайт памяти даже на простом с виду цикле. Для Python 3.xx это не требуется.


Си

Вывод чисел от 1 до 9:

      for(int i=1; i<10; i++) {

       printf("%d\n", i);

      }


Вывод чисел от 1 до 9 с шагом 2:

      for(int i=1; i<10; i+=2) {

       printf("%d\n", i);

      }


Массивы


Массив это линейный набор чисел, с которыми удобно выполнять однотипные операции, например вычисление суммы или среднего арифметического.


Python:

Объявляем массив чисел:

values = [1,2,3,5,10,15,20]


Добавляем элемент в массив:

values.append(7)


Выводим массив на экран:

print (values)


Выводим элементы массива построчно:

for p in values:

print (p)


Это же можно сделать с помощью индексов (нумерация элементов массива начинается с 0):

for i in range(0,len(values)):

print (values[i])


Можно создать массив определенного размера, заполненный определенными числами. Создадим массив из 100 элементов, заполненный нулями.

values = [0.0] * 100

print (values)


Есть немного более сложный, но и более гибкий вариант создания массива. Создадим массив из 100 элементов, заполненный нулями:

values = [0.0 for i in range(100)]

Создадим массив, заполненный числами 0,1,..,99:

values = [i for i in range(100)]


Создадим массив, заполненный квадратами чисел:

values = [i*i for i in range(100)]


Создать двухмерный массив в Python также несложно:

matrix4x4 = [ [0,0,0,0], [0,0,0,0], [0,0,0,0], [0,0,0,0]]

matrix4x4[0][0] = 1

print (matrix4x4)


Аналогично вышеописанному способу, можно создать 2х-мерный массив 100x100:

values100x100 = [ [0.0 for j in range(100)] for i in range(100)]


Си:

Динамические массивы поддерживаются только в C++, статические массивы создаются так:


int values[7] = { 1,2,3,5,10,15,20 };

for(int i=0; i<7; i++) {

printf("%d\n", values[i]);

}


При желании можно слегка схитрить, если максимальный размер массива заранее известен.

int values[255] = { 1,2,3,5,10,15,20 }, cnt = 7;

for(int i=0; i<cnt; i++) {

printf("%d\n", values[i]);

}

values[cnt] = 7;

cnt++;


Можно пользоваться динамическим распределением памяти, хотя это немного сложнее:

int *valuesArray = (int*)malloc(10*sizeof(int));

valuesArray[0] = 1;

valuesArray[1] = 3;

valuesArray[2] = 15;

valuesArray = (int*)realloc(valuesArray, 25*sizeof(int));

valuesArray[20] = 555;

valuesArray[21] = 777;

for(int i=0; i<25; i++) {

printf("%d\n", valuesArray[i]);

}

free(valuesArray);


Важно заметить, что неинициализированные значения массива, например valuesArray[16], будут содержать “мусор”, некие значения которые были до этого в памяти. Си достаточно низкоуровневый язык, и такие моменты нужно учитывать. Хорошим тоном является инициализация всех переменных при их описании. Вот такой код формально не содержит ошибок:

int x;

printf("x=%d\n", x);


Однако при его запуске выведется значение 4196608, или 0, или 32, результат непредсказуем. В большой программе такие ошибки может быть сложно найти, тем более что проявляться они могут не всегда.


Арифметические операции


Сложение, умножение, деление:

x1 = 3

x2 = (2*x1*x1 + 10*x1 + 7)/x1


Возведение в степень:

x3 = x1**10

print (x1,x2,x3)


Переменную также можно увеличить или уменьшить:

x1 += 1

x1 -= 10

print (x1)


Остаток от деления:

x2 = x1 % 6

print (x2)


Условия в Python кстати, задаются отступами, аналогично циклам:

print (x1)

if x1 % 2 == 0:

print("x1 четное число")

else:

print("x1 нечетное число")


Подсчитаем сумму элементов массива:

values = [1,2,3,5,10,15,20]

s = 0

for p in values:

s += p

print(s)


Также для этого можно воспользоваться встроенной функцией sum:

values = [1,2,3,5,10,15,20]

print(sum(values))


В Си вычисление суммы элементов массива выглядит так:

int sum = 0;

for(int i=0; i<cnt; i++) {

       sum += values[i];

      }

      printf("Sum=%d\n", sum);


Для более сложных операций в Python необходимо подключить модуль math. Вычисление квадратного корня:

import math


print (math.sqrt(x3))


Python может делать вычисления с большими числами, что достаточно удобно:

import math


x1 = 12131231321321312312313131124141

print (10*x1)

print (math.sqrt(x1))


Можно вывести даже факториал числа 1024, что не сделает ни один калькулятор:

import math


print(math.factorial(1024))


Пожалуй, этого не хватит чтобы устроиться на работу программистом, но вполне достаточно для понимания большинства примеров в книге. Теперь вернемся к математике.


2. Математические фокусы

Для “разминки” рассмотрим несколько фокусов, имеющих отношение к числам. Никаких особых сложностей в них нет, но их знание поможет развеселить или удивить знакомых знанием математики.


Умножение в уме числа на 11

Рассмотрим простой пример:

26*11 = 286


Сделать это в уме просто, если взять сумму чисел и поместить в середину:

26*11 = 2 [ 2+6 ] 6

Аналогично 43*11 = 473, 71*11 = 781 и так далее.


Чуть длиннее расчет, если сумма чисел больше либо равна 10. Но и тогда все просто: в середину кладется младший разряд, а 1 уходит в старший разряд:

47*11 = [4] [4+7=11] [7] = [4+1] [1] [7] = 517

94*11 = [9] [9+4=13] [4] = [10] [3] [4] = 1034


Возведение в квадрат числа, оканчивающегося на 5

Подсчитать это тоже просто. Если число рассмотреть как пару NM, то первая часть результата - это число N, умноженное на (N+1), вторая часть числа - всегда 25.

352 = [3*4] [25] = 12 25


Аналогично:

252 = [2*3] 25 = 625      852 = [8*9] 25 = 7225 и так далее.


Отгадывание результата

Попросим человека загадать любое число. Например 73. Затем чтобы еще больше запутать отгадывающего, попросим сделать следующие действия:

удвоим число (146)

прибавляем 12 (158)

разделим на 2 (79)

вычтем из результата исходное число (79-73 = 6)

В конце мы отгадываем, что результат - 6. Суть в том, что число 6 появляется независимо от того, какое число загадал человек.


Математически, это доказывается очень просто:

(2*n + 12)/2 - n = n + 6 - n = 6, независимо от значения n.


Отгадывание чисел

Есть другой фокус с отгадыванием чисел. Попросим человека загадать трехзначное число, числа в котором идут в порядке уменьшения (например 752). Попросим человека выполнить следующие действия:

записать число в обратном порядке (257)

вычесть его из исходного числа (752 - 257 = 495)

к ответу добавить его же, только в обратном порядке (495 + 594)

Получится число 1089, которое “фокусник” и объявляет публике.


Математически это тоже несложно доказать.

Любое число вида abc в десятичной системе счисления представляется так:

abc = 100*a + 10*b +c.

Разность чисел abc - cba:

100*a + 10*b +c + 100 - 100*c-10*b - a = 100*a - 100*c - (a - c) = 100*(a-c) - (a-c)

Т.к. по условию a - c > 0, то результат можно записать в виде:

100*(a-c) - (a-c) = 100*(a-c) - 100 + 90 + 10 - (a-c) = 100*(a-c-1) + 10*9 + (10-a+c)

Мы узнали разряды числа, получающегося в результате:

a1=a-c-1, b1 = 9, c1 =10-a+c

Добавляем число в обратном порядке:

a1b1c1 + c1b1a1 = 100*(a-c-1) + 10*9 + (10-a+c) + 100* (10-a+c) + 10*9 + a-c-1

Если раскрыть все скобки и сократить лишнее, в остатке будет 1089.

3. Число Пи

Вобьем в стену гвоздь, привяжем к нему веревку с карандашом, начертим окружность. Как вычислить длину окружности? Сегодня ответ знает каждый школьник - с помощью числа Пи. Число Пи - несомненно, одна из основных констант мироздания, значение которой было известно еще в древности. Оно используется везде, от кройки и шитья до расчетов гармонических колебаний в физике и радиотехнике.


Сегодня достаточно нажать одну кнопку на калькуляторе, чтобы увидеть его значение: ...




Все права на текст принадлежат автору: Дмитрий Витальевич Елисеев.
Это короткий фрагмент для ознакомления с книгой.
Рассказы о математике с примерами на языках Python и CДмитрий Витальевич Елисеев