Раздел: Как стать программистом / Секреты программирования /

Сложные математические формулы в программировании

Все способы изучить Python Все способы изучить Python

Каждый раз, изучая какую-то новую науку, мы задаёмся вопросом - где взять обучающие материалы. Конечно, сегодня нам помогает в этом Интернет. Но иногда на поиски уходит очень много времени, а нужного результата мы не получаем... Собрал для вас кучу полезных ссылок для изучения Python. не благодарите ))) Подробнее...

Недавно меня выгнали с работы, поэтому сейчас пытаюсь зарабатывать фрилансом. И вот подвернулась задачка - надо было перевести формулы с языка математики на язык программирования. В случае с простыми формулами это делается достаточно легко. Ведь операторы, такие как +, -, * и т.п. одинаково выглядят как в математике, так и в языках программирования.

Однако, если формулы достаточно сложные, то здесь уже становится не так весело. И времени на эту работу уходит достаточно много. И ошибок можно допустить немало, которые потом трудно выискивать.

Так что сегодня поделюсь своими хитростями работы с математическими формулами в программировании. Надеюсь, кому-нибудь окажется полезным.

Итак, вот пример такой формулы:

Сложная математическая формула

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

Можно и так. Но лучше выделить в формулах повторяющиеся выражения и для каждого выражения создать отдельную функцию. А потом уже просто вызывать эти функции с необходимыми параметрами.

В итоге наша формула будет выглядеть примерно так:

Разбиение сложной формулы на отдельные выражения

А вот так это может быть выполнено в исходном коде программы:

type Point3 = record
  x1, y1, z1 : Extended;
  x2, y2, z2 : Extended;
  x3, y3, z3 : Extended;
end;

// Вспомогательные функции
// (x1 - x2)^2 + (y1 - y2)^2 + (z1 - z2)^2
function a(p : Point3) : Extended;
begin
  Result := Sqr(p.x1 - p.x2) + Sqr(p.y1 - p.y2) + Sqr(p.z1 - p.z2);
end;

// (x3 - x2)^2 + (y3 - y2)^2 + (z3 - z2)^2
function b(p : Point3) : Extended;
begin
  Result := Sqr(p.x3 - p.x2) + Sqr(p.y3 - p.y2) + Sqr(p.z3 - p.z2);
end;
// (x1 - x3)^2 + (y1 - y3)^2 + (z1 - z3)^2
function c(p : Point3) : Extended;
begin
  Result := Sqr(p.x1 - p.x3) + Sqr(p.y1 - p.y3) + Sqr(p.z1 - p.z3);
end;

// F
function F(p : Point3) : Extended;
var chis, znam : Extended;
begin
  chis := (a(p) + b(p) - c(p));
  znam := 2 * Sqrt(a(p)) * Sqrt(b(p));
  Result := chis / znam;
end;

Ну и для закрепления рассмотрим ещё один пример, посложнее:

Ещё более сложная формула

Здесь всё выглядит ещё страшнее. Но если присмотреться, то мы здесь увидим уже известные нам выражения, которые мы выделили в первом примере и назвали а, b и c. И эти выражения повторяются в функциях Z01 и Z02, Отличаются эти функции только двумя выражениями (на рисунке ниже я обозначил их как n1 и n2). Поэтому в нашей программе мы можем использовать уже готовые функции а, b и c в новых функциях Z01 и Z02, а упрощённая формула будет такой:

Упрощённая сложная формула

Тогда программный код может быть таким:

//Вспомогательная функция для вычисления Z01...Z2
function Za(p : Point3; n1, n2 : Extended) : Extended;
var r1, r2, r3 : Extended;
begin
	r1 := 2 * Sqrt(a(p)) * Sqrt(b(p));
	r2 := a(p) + b(p) - c(p);
	r3 := 4 * Exp(1.5 * Ln(a(p))) * sqrt(b(p));

  Result := (n1 / r1) - (r2 * n2 / r3);
end; 

// Z01
function Z01(p : Point3) : Extended;
var n1, n2 : Extended;
begin
  n1 := -2*p.x2 + 2*p.x3;
  n2 := 2*p.x1 - 2*p.x2;
  Result := Za(p, n1, n2);
end;

// Z02
function Z02(p : Point3) : Extended;
var n1, n2 : Extended;
begin
  n1 := -2*p.y2 + 2*p.y3;
	n2 := 2*p.y1 - 2*p.y2;
  Result := Za(p, n1, n2);
end;

Как видите, я добавил здесь вспомогательную функцию Za, чтобы уменьшить количество кода в функциях Z01 и Z02. Конечно, если у вас только две таких функции, то вспомогательные функции можно и не делать. Но если 10, 20 и больше, то такой подход существенно уменьшит количество исходного кода и размер исходного файла.

Ну и напоследок ещё один полезный совет - как не запутаться в скобках. В указанных выше примерах скобок не так много, поэтому запутаться сложно. Однако бывают и более навороченные формулы, где запутаться в скобках очень легко. Поэтому, если есть файл с формулами, то я преобразую его в формат рисунка (например, в JPG), открываю в графическом редакторе и там выделяю выражения и отмечаю скобки. Примерно так:

Выделение скобок в сложной формуле

То есть открывающую и закрывающую скобку я выделяю одним цветом. Следующую пару скобок - другим цветом и так далее. И таким образом я выделяю в формуле выражения, которые потом можно перенести в исходный код программы.

Ну что же, на этом всё. Надеюсь, кому-нибудь это поможет сократить время на решение подобных задач. Математика в программировании - это не так уж скучно. Особенно если за это платят деньги )))


Директивы компилятора Директивы компилятора
Как это ни странно, но даже многие опытные программисты не используют директивы компилятора, считая их чем-то ненужным и бесполезным. А между тем, директивы компилятора - это очень классная штука. Если их умело применять в своих программах, то можно существенно сократить время на разработку и уменьшить количество рутинных операций. Подробнее...
Инфо-МАСТЕР ®
Все права защищены ©
e-mail: mail@info-master.su

Яндекс.Метрика