Елисеев Д.
Рассказы о математике с примерами на языках Python и C.
Версия текста 1.0. (с) 2017
Введение
Как сказал еще Галилей, “Книга природы написана на языке математики”, и с этим сложно не согласиться. Математика это универсальный язык науки, это базовые принципы, на которых построена вся Вселенная. 2+2=4 независимо от того, верим мы в это или нет, знаем мы это или нет, существуем мы вообще или нет, и это будет верно не только для нас, но и для жителя Альфы Центавра.
Из этого следует важное правило: математические законы нельзя придумать, их можно только открыть. Треугольник подчинялся теореме Пифагора еще до того, как Пифагор открыл и сформулировал известную теорему. Число Пи было вычислено в древнем Китае, но его значение было таким всегда - еще до того как появился не только Китай, но и наша планета Земля.
Именно поэтому я надеюсь, что кто-то из читателей с помощью этой книги откроет для себя в математике что-то новое. Увы, в представлении большинства, математика - это достаточно скучная наука, вероятно так ее преподают в школе. Если кто-то с помощью этой книги найдет для себя что-то новое, можно считать что время было потрачено не зря.
Эта книга не задачник, а скорее сборник рассказов о тех или иных математических вопросах. Т.к. математические примеры без цифр бессмысленны, “практическая” часть дается на языках программирования Python и Си.
Номер версии в заголовке указан неслучайно. Эта книга не закончена, и по мере появления каких-то новых интересных вопросов она будет дополняться. Желающие также могут присылать свои истории или задачи по адресу dmitryelj@gmail.com, наиболее интересные из них будут включены в текст. Обо найденных неточностях также просьба писать на этот адрес.
Книга распространяется бесплатно в электронном виде. Печатную версию желающие могут сделать себе самостоятельно. В архиве также приложены все файлы программ. Наличие новой версии можно проверить на странице http://dmitryelj.spb.ru/math.htm.
Приятного чтения.
Елисеев Дмитрий
История версий текста:
04.2017 - 1.0
1. Основы языков Python и Си
Математика немыслима без расчетов и примеров вычислений. Примеры в данной книге иллюстрируются фрагментами кода на языке Python. Этот язык удобен тем, что он очень прост и подходит для начинающих, поэтому кратко рассмотрим как им пользоваться.
Для использования языка Python нужно установить интерпретатор языка с сайта https://www.python.org/downloads/ или воспользоваться онлайн-версией, например на странице https://repl.it/languages/python3. Все примеры из книги работоспособны с любой версией языка Python, 2.7 или 3.
Для запуска программы необходимо:
- Сохранить файл в Блокноте с любым именем и расширением .py, например test1.py (удобно также создать папку в корне диска C, например C:\PythonApps).
- Открыть консоль (нажать Win+R и набрать cmd), в консоли набрать команду (без кавычек) “python путь_к_файлу.py”, например “python C:\PythonApps\test1.py”.
Как более удобный вариант, можно скачать бесплатную среду разработки PyСharm community edition, и редактировать и запускать файлы в ней. Скачать PyСharm можно со страницы https://www.jetbrains.com/pycharm/download/.
Для запуска программы на языке Си, ее сначала надо сохранить файле с расширением .c, и выполнить команду “gcc имя_файла.c”. Будет создан exe-файл, который можно запустить.
Минимальная программа на Си выглядит так:
#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)).
Cи: необходимо указать тип и значение переменной.
int x = 3;
int y = 10;
printf("x=%d\n", x);
printf("%d\n", x+y);
Циклы
В отличие от того же С++ или Java, циклы задаются отступами, что после других языков программирования может быть непривычным. Часть кода, находящаяся внутри цикла, будет выполнена заданное количество раз.
Python
Вывод чисел от 1 до 9:
for p in range(1,10):
print (p)
Вывод чисел от 1 до 9 с шагом 2:
for p in range(1,10,2):
print (p)
Си
Вывод чисел от 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])
Си: Динамические массивы поддерживаются только в 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)
Подсчитаем сумму элементов массива:
values = [1,2,3,5,10,15,20]
sum = 0
for p in values:
sum += p
print (sum)
Для более сложных операций необходимо подключить модуль math. Вычисление квадратного корня:
import math
print (math.sqrt(x3))
Условия задаются отступами, аналогично циклам:
print (x1)
if x1 % 2 == 0:
print("x1 четное число")
else:
print("x1 нечетное число")
Python может делать вычисления с большими числами, что достаточно удобно:
x1 = 12131231321321312312313131124141
print (10*x1)
print (math.sqrt(x1))
Можно вывести даже факториал числа 1024, что не сделает ни один калькулятор:
print(math.factorial(1024))
В Си вычисление суммы элементов массива выглядит так:
int sum = 0;
for(int i=0; i<cnt; i++) {
sum += values[i];
}
printf("Sum=%d\n", sum);
Пожалуй, этого не хватит чтобы устроиться на работу программистом, но вполне достаточно для понимания большинства примеров в книге. Теперь вернемся к математике.
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. Число Пи
Вобьем в стену гвоздь, привяжем к нему веревку с карандашом, начертим окружность. Как вычислить длину окружности? Сегодня ответ знает каждый школьник - с помощью числа Пи. Число Пи - несомненно, одна из основных констант мироздания, значение которой было известно еще в древности. Оно используется везде, от кройки и шитья до расчетов гармонических колебаний в физике и радиотехнике.
Сегодня достаточно нажать одну кнопку на калькуляторе, чтобы увидеть его значение:
Pi = 3.1415926535… Однако, за этими цифрами скрывается многовековая история. Что такое число Пи? Это отношение длины окружности к ее диаметру. То что это константа, не зависящая от самой длины окружности, знали еще в древности. Но чему она равна? Есть ли у этого числа какая-то внутренняя структура, неизвестная закономерность? Узнать это хотели многие. Самый простой и очевидный способ - взять и измерить. Примерно так вероятно и поступали в древности, точность разумеется была невысокой. Еще в древнем Вавилоне значение числа Пи было известно как 25/8. Затем Архимед предложил первый математический метод вычисления числа Пи, с помощью расчета вписанных в круг многоугольников. Это позволяло вычислять значение не «напрямую», с циркулем и линейкой, а математически, что обеспечивало гораздо большую точность. И наконец в 3-м веке нашей эры китайский математик Лю Хуэй придумал первый итерационный алгоритм — алгоритм, в котором число вычисляется не одной формулой, а последовательностью шагов (итераций), где каждая последующая итерация увеличивает точность. С помощью своего метода Лю Хуэй получил Пи с точностью 5 знаков: π = 3.1416. Дальнейшее увеличение точности заняло сотни лет. Математик из Ирана Джамшид ибн Мас‘уд ибн Махмуд Гияс ад-Дин ал-Каши в 15-м веке вычислил число Пи с точностью до 16 знаков, а в 17-м веке голландский математик Лудольф вычислил 32 знака числа Пи. В 19-м веке англичанин Вильям Шенкс, потратив 20 лет, вычислил Пи до 707 знака, однако он так и не узнал, что в 520-м знаке допустил ошибку и все последние годы вычислений оказались напрасны (в итерационных алгоритмах хоть одна ошибка делает все дальнейшие шаги бесполезными).