PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Описание: Класс для решения алгебраических уравнений до 5-й степени
EuGen Администратор
Отправлено: 22 Января, 2013 - 14:04:24
Post Id


Профессионал


Покинул форум
Сообщений всего: 9097
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Представляю вашему вниманию класс, который позволяет решать алгебраические уравнения до 4-й степени включительно в вещественных корнях аналитически известными методами.
Для уравнений более высоких порядков существуют численные методы решения (я имею ввиду аппроксимирующие итерации по методам Рунге-Кутта) - возможно, в дальнейшем я добавлю такую возможность. Однако этот метод весьма ресурсоемок, аналитических же методов решения уравнений степени, превышающей 4, не существует ввиду того, что корни таких уравнений в общем случае не являются алгебраическими числами (то есть не выразимы в радикалах) - согласно теореме Абеля-Руфини.

Для уравнений до 2-й степени включительно текущая версия класса так же позволяет получить решение в виде радикала, то есть указывается формула с подставленными числовыми значениями, по которой можно получить точное значение корня.
Для уравнений 3-й и 4-й степени это так же возможно сделать, но вычисления проводятся по методам Виета и Феррари соответственно (от формулы Кардано я отказался по причине трудоемкости практического её применения из-за необходимости вариативных вычислений над полем комплексных чисел), что делает такие построения чересчур громоздкими и трудночитаемыми в терминах CLI-разделителей, а потому практически бесполезными.

PHP:
скопировать код в буфер обмена
  1. class Equation
  2. {
  3.     const ROOT_EXACT = 'point';
  4.     const ROOT_RANGE = 'range';
  5.     const ROOT_RANGE_FROM = 'range_from';
  6.     const ROOT_RANGE_TILL = 'range_till';
  7.     const SOLVE_ALGEBRAIC = 1;
  8.     const SOLVE_EXACT     = 0;
  9.     const FLOAT_EQUATION_DELTA = 1E-15;
  10.  
  11.     protected $_iPower = 0;
  12.     protected $_rgCoef = array();
  13.        
  14.     public function __construct()
  15.     {
  16.         $rgArgs = func_get_args();
  17.         if(!count($rgArgs))
  18.         {
  19.             return null;
  20.         }
  21.         $rgCoef = is_array($rgArgs[0])?$rgArgs[0]:$rgArgs;
  22.         $this->_iPower = count($rgCoef)-1;
  23.         for($i=0; $i<=$this->_iPower; $i++)
  24.         {
  25.             $this->_rgCoef[$this->_iPower-$i] = $rgCoef[$i];
  26.         }
  27.         $i=$this->_iPower;
  28.         //strip zero-multiplied high powers, if any, with reducing whole power:
  29.         while(!$this->_rgCoef[$i] && $i>0)
  30.         {
  31.             unset($this->_rgCoef[$i]);
  32.             $i--;
  33.             $this->_iPower--;
  34.         }
  35.     }
  36.  
  37.     public function solveEquation($mFlag=self::SOLVE_EXACT)
  38.     {
  39.         $sMethod = '_solve_power_'.$this->_iPower;
  40.         if(method_exists($this, $sMethod))
  41.         {
  42.             return $this->$sMethod($mFlag);
  43.         }
  44.         return null;
  45.     }
  46.    
  47.     public function getAlgebraic($sVariable='z', $sPowerDelimiter='^')
  48.     {
  49.         $rgPrints = array();
  50.         $rgCoef   = $this->_rgCoef;
  51.         krsort($rgCoef);
  52.         array_walk($rgCoef, function($fValue, $iKey) use (&$rgPrints, $sVariable, $sPowerDelimiter)
  53.         {
  54.             if($fValue)
  55.             {
  56.                 $rgPrints[] = $iKey?($fValue!=1?$fValue:'').$sVariable.($iKey!=1?$sPowerDelimiter.$iKey:''):$fValue;
  57.             }
  58.         });
  59.         return str_replace('+ -','- ',join(' + ', $rgPrints));
  60.     }
  61.  
  62.     protected function _solve_power_0($mFlag=self::SOLVE_EXACT, $rgCoef=null)
  63.     {
  64.         $rgCoef=isset($rgCoef)&&is_array($rgCoef)?$rgCoef:$this->_rgCoef;
  65.         if(!$rgCoef[0])
  66.         {
  67.             return array(
  68.                     self::ROOT_RANGE=>array(self::ROOT_RANGE_FROM=>-INF, self::ROOT_RANGE_TILL=>INF),
  69.                     );
  70.         }
  71.         else
  72.         {
  73.             return array();
  74.         }
  75.     }
  76.  
  77.     protected function _solve_power_1($mFlag=self::SOLVE_EXACT, $rgCoef=null)
  78.     {
  79.         $rgCoef=isset($rgCoef)&&is_array($rgCoef)?$rgCoef:$this->_rgCoef;
  80.         if($mFlag==self::SOLVE_ALGEBRAIC)
  81.         {
  82.             $sCoef   = -1*($rgCoef[0]/$rgCoef[1])<0?'-':'';
  83.             $mResult = $rgCoef[0]?$sCoef.abs($rgCoef[0]).'/'.abs($rgCoef[1]):'0';
  84.         }
  85.         else
  86.         {
  87.             $mResult = -1*$rgCoef[0]/$rgCoef[1];
  88.         }
  89.         return array(self::ROOT_EXACT=>array($mResult));
  90.     }
  91.  
  92.     protected function _solve_power_2($mFlag=self::SOLVE_EXACT, $rgCoef=null)
  93.     {
  94.         $rgCoef=isset($rgCoef)&&is_array($rgCoef)?$rgCoef:$this->_rgCoef;
  95.         $fDiscriminant = pow($rgCoef[1],2)-4*$rgCoef[0]*$rgCoef[2];
  96.         if($this->_compare_floats($fDiscriminant, 0))
  97.         {
  98.             $sCoef       = -1*($rgCoef[1]/$rgCoef[2])<0?'-':'';
  99.             $mResult = $mFlag==self::SOLVE_EXACT?-1*$rgCoef[1]/(2*$rgCoef[2]):$sCoef.abs($rgCoef[1]).'/(2*'.abs($rgCoef[2]).')';
  100.             return array(
  101.                     self::ROOT_EXACT=>array($mResult)
  102.             );
  103.         }
  104.         elseif($fDiscriminant<0)
  105.         {
  106.             return array();
  107.         }
  108.  
  109.         else
  110.         {
  111.             if($mFlag==self::SOLVE_EXACT)
  112.             {
  113.                 $rgRoots = array(
  114.                         (-1*$rgCoef[1]+sqrt($fDiscriminant))/(2*$rgCoef[2]),
  115.                         (-1*$rgCoef[1]-sqrt($fDiscriminant))/(2*$rgCoef[2]));
  116.             }
  117.             else
  118.             {
  119.                 $sCoefB = $this->_get_algebraic_sign_single(-1*$rgCoef[1]);
  120.                 $sCoefA = $this->_get_algebraic_sign_single(-1*$rgCoef[2]);
  121.                 $sCoefD = -1*$rgCoef[2]*$rgCoef[0]<0?'-':'+';
  122.                 $sSummD = $rgCoef[0]?$sCoefD.'4*'.abs($rgCoef[2]).'*'.abs($rgCoef[0]):'';
  123.                 $sSummB0= '';
  124.                 $sSummB1= '';
  125.                 if($rgCoef[1])
  126.                 {
  127.                         $sSummB0 = $sCoefB.abs($rgCoef[1]);
  128.                         $sSummB1 = 'pow('.$rgCoef[1].',2)';
  129.                 }
  130.                 $rgRoots = array(
  131.                         $sCoefA.'('.$sSummB0.'+sqrt('.$sSummB1.$sSummD.'))/(2*'.$rgCoef[2].')',
  132.                         $sCoefA.'('.$sSummB0.'-sqrt('.$sSummB1.$sSummD.'))/(2*'.$rgCoef[2].')'
  133.                 );
  134.             }
  135.             return array(self::ROOT_EXACT=>$rgRoots);
  136.         }
  137.     }
  138.     //Viett method on resolving 3-power equation
  139.     protected function _solve_power_3($mFlag=self::SOLVE_EXACT, $rgCoef=null)
  140.     {
  141.         $rgCoef     = isset($rgCoef)&&is_array($rgCoef)?$rgCoef:$this->_rgCoef;
  142.         $fMajor     = $rgCoef[3];
  143.         $rgCoef     = array_map(function($fItem) use ($fMajor)
  144.         {
  145.             return $fItem/$fMajor;
  146.         }, $rgCoef);
  147.         $fQ         = (pow($rgCoef[2],2)-3*$rgCoef[1])/9;
  148.         $fR         = (2*pow($rgCoef[2],3)-9*$rgCoef[2]*$rgCoef[1]+27*$rgCoef[0])/54;
  149.         $fS         = pow($fQ,3)-pow($fR,2);
  150.         if($fS>0)
  151.         {
  152.             $fPhi   = acos($fR/pow($fQ,1/3))/3;
  153.             $rgRoots= array(
  154.                 -2*pow($fQ,1/2)*cos($fPhi)-$rgCoef[2]/3,
  155.                 -2*pow($fQ,1/2)*cos($fPhi+2*pi()/3)-$rgCoef[2]/3,
  156.                 -2*pow($fQ,1/2)*cos($fPhi-2*pi()/3)-$rgCoef[2]/3,
  157.             );
  158.         }
  159.         elseif($fS<0)
  160.         {
  161.             if($fQ>0)
  162.             {
  163.                 $fPhi   = acosh(abs($fR)/$this->_get_algebraic_root(pow(abs($fQ),3),2))/3;
  164.                 $rgRoots= array(-2*$this->_get_sgn($fR)*$this->_get_algebraic_root(abs($fQ),2)*cosh($fPhi)-$rgCoef[2]/3);
  165.             }
  166.             else
  167.             {
  168.                 $fPhi   = asinh(abs($fR)/$this->_get_algebraic_root(pow(abs($fQ),3),2))/3;
  169.                 $rgRoots= array(-2*$this->_get_sgn($fR)*$this->_get_algebraic_root(abs($fQ),2)*sinh($fPhi)-$rgCoef[2]/3);
  170.             }
  171.         }
  172.         else
  173.         {
  174.             if($fR)
  175.             {
  176.                 $rgRoots=array(
  177.                     -2*$this->_get_algebraic_root($fR,3)-$rgCoef[2]/3,
  178.                     $this->_get_algebraic_root($fR,3)-$rgCoef[2]/3
  179.                 );
  180.             }
  181.             else
  182.             {
  183.                 $rgRoots=array(-1*$rgCoef[2]/3);
  184.             }
  185.         }
  186.         $rgRoots    = array_map(function($fItem)
  187.         {
  188.             return $this->_compare_floats(round($fItem), $fItem)?round($fItem):$fItem;
  189.         }, $rgRoots);
  190.         return array(self::ROOT_EXACT=>$rgRoots);
  191.     }
  192.     //Ferrari method of resolving 4-power equation
  193.     protected function _solve_power_4($mFlag=self::SOLVE_EXACT, $rgCoef=null)
  194.     {
  195.         $rgCoef     = isset($rgCoef)&&is_array($rgCoef)?$rgCoef:$this->_rgCoef;
  196.         $fAlpha     = (-3*pow($rgCoef[3],2))/(8*pow($rgCoef[4],2))+$rgCoef[2]/$rgCoef[4];
  197.         $fBeta      = pow($rgCoef[3],3)/(8*pow($rgCoef[4],3))-($rgCoef[3]*$rgCoef[2])/(2*pow($rgCoef[4],2))+$rgCoef[1]/$rgCoef[4];
  198.         $fGamma     = (-3*pow($rgCoef[3],4))/(256*pow($rgCoef[4],4))+pow($rgCoef[3],2)*$rgCoef[2]/(16*pow($rgCoef[4],3))-$rgCoef[3]*$rgCoef[1]/(4*pow($rgCoef[4],2))+$rgCoef[0]/$rgCoef[4];
  199.         $rgRoots    = array();
  200.         if($this->_compare_floats(0, $fBeta))
  201.         {
  202.             if(($fResolventaD = pow($fAlpha,2)-4*$fGamma)<0)
  203.             {
  204.                 return array();
  205.             }
  206.             if(($fSqrtNeg = -1*$fAlpha-$this->_get_algebraic_root($fResolventaD, 2))>=0)
  207.             {
  208.                 $rgRoots = array_merge($rgRoots, array(
  209.                     -1*$rgCoef[3]/(4*$rgCoef[4])+$this->_get_algebraic_root($fSqrtNeg/2, 2),
  210.                     -1*$rgCoef[3]/(4*$rgCoef[4])-$this->_get_algebraic_root($fSqrtNeg/2, 2)
  211.                 ));
  212.             }
  213.             if(($fSqrtPos = -1*$fAlpha+$this->_get_algebraic_root($fResolventaD, 2))>=0)
  214.             {
  215.                 $rgRoots = array_merge($rgRoots, array(
  216.                     -1*$rgCoef[3]/(4*$rgCoef[4])+$this->_get_algebraic_root($fSqrtPos/2, 2),
  217.                     -1*$rgCoef[3]/(4*$rgCoef[4])-$this->_get_algebraic_root($fSqrtPos/2, 2)
  218.                 ));
  219.             }
  220.         }
  221.         else
  222.         {
  223.             $fP = -1*pow($fAlpha,2)/12-$fGamma;
  224.             $fQ = -1*pow($fAlpha,3)/108+$fAlpha*$fGamma/3-pow($fBeta,2)/8;
  225.             if(($fResolventaD = pow($fQ,2)/4+pow($fP,3)/27)<0)
  226.             {
  227.                 return array();
  228.             }
  229.             $fR = -1*$fQ/2+$this->_get_algebraic_root($fResolventaD, 2);
  230.             $fU = $this->_get_algebraic_root($fR, 3);
  231.             $fY = -5*$fAlpha/6+$fU+($fU?((-1*$fP)/(3*$fU)):(-1*$this->_get_algebraic_root($fQ, 3)));
  232.             if(($fW = $fAlpha+2*$fY)<0)
  233.             {
  234.                 return array();
  235.             }
  236.             $fW = $this->_get_algebraic_root($fW, 2);
  237.             if(($fSqrtNeg = -1*(3*$fAlpha+2*$fY-2*$fBeta/$fW))>=0)
  238.             {
  239.                 $rgRoots = array_merge($rgRoots, array(
  240.                     -1*$rgCoef[3]/(4*$rgCoef[4])+(-1*$fW+$this->_get_algebraic_root($fSqrtNeg, 2))/2,
  241.                     -1*$rgCoef[3]/(4*$rgCoef[4])+(-1*$fW-$this->_get_algebraic_root($fSqrtNeg, 2))/2
  242.                 ));
  243.             }
  244.             if(($fSqrtPos = -1*(3*$fAlpha+2*$fY+2*$fBeta/$fW))>=0)
  245.             {
  246.                 $rgRoots = array_merge($rgRoots, array(
  247.                     -1*$rgCoef[3]/(4*$rgCoef[4])+($fW+$this->_get_algebraic_root($fSqrtPos, 2))/2,
  248.                     -1*$rgCoef[3]/(4*$rgCoef[4])+($fW-$this->_get_algebraic_root($fSqrtPos, 2))/2
  249.                 ));
  250.             }
  251.         }
  252.         //since Ferrari method have no guarantee from duplicate roots, do following:
  253.         $rgRoots    = array_unique(array_map(function($fItem)
  254.         {
  255.             return $this->_compare_floats(round($fItem), $fItem)?round($fItem):$fItem;
  256.         }, $rgRoots));
  257.         return array(self::ROOT_EXACT=>$rgRoots);
  258.     }
  259.  
  260.     protected function _compare_floats($fLeft, $fRight)
  261.     {
  262.         return abs((double)$fLeft-(double)$fRight)<self::FLOAT_EQUATION_DELTA;
  263.     }
  264.     //Sign functions:
  265.     //for string representation:
  266.     protected function _get_algebraic_sign_single($fNumeric)
  267.     {
  268.         return $fNumeric<0?'-':'';
  269.     }
  270.     //for exact calculation:
  271.     protected function _get_sgn($fArg)
  272.     {
  273.         if($fArg<0)
  274.         {
  275.             return -1;
  276.         }
  277.         return 1;
  278.     }
  279.     //since pow(x,1/N) didn't work properly, function below is needed:
  280.     protected function _get_algebraic_root($fArg, $iRoot)
  281.     {
  282.         if(!is_int($iRoot))
  283.         {
  284.             return null;
  285.         }
  286.         if(!$iRoot)
  287.         {
  288.             return $fArg?1:NaN;
  289.         }
  290.         if($fArg>=0)
  291.         {
  292.             return pow($fArg, 1/$iRoot);
  293.         }
  294.         else
  295.         {
  296.             if($iRoot%2)
  297.             {
  298.                 return -1*pow(abs($fArg), 1/$iRoot);
  299.             }
  300.             else
  301.             {
  302.                 return NaN;
  303.             }
  304.         }
  305.     }
  306. }


Пример использования: equation.php:
PHP:
скопировать код в буфер обмена
  1. //includes omitted
  2. $rEquation = new Equation(explode(',', $_SERVER['argv'][1]));
  3. echo($rEquation->getAlgebraic()."\n");
  4. var_dump($rEquation->solveEquation(Equation::SOLVE_EXACT));


Результаты:
CODE (bash):
скопировать код в буфер обмена
  1. user@host:/path$ php equation.php 1,-10,35,-50,24
  2. z^4 - 10z^3 + 35z^2 - 50z + 24
  3. array(1) {
  4.   ["point"]=>
  5.   array(4) {
  6.     [0]=>
  7.     float(3)
  8.     [1]=>
  9.     float(2)
  10.     [2]=>
  11.     float(4)
  12.     [3]=>
  13.     float(1)
  14.   }
  15. }
  16. user@host:/path$ php equation.php 1,0,1          
  17. z^2 + 1
  18. array(0) {
  19. }
  20. user@host:/path$ php equation.php 1,-6,11,-6
  21. z^3 - 6z^2 + 11z - 6
  22. array(1) {
  23.   ["point"]=>
  24.   array(3) {
  25.     [0]=>
  26.     float(1)
  27.     [1]=>
  28.     float(3)
  29.     [2]=>
  30.     float(2)
  31.   }
  32. }

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


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
DeepVarvar Супермодератор
Отправлено: 22 Января, 2013 - 14:34:41
Post Id



Активный участник


Покинул форум
Сообщений всего: 10378
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


Помог: 353 раз(а)




EuGen пишет:
... Рунге-Кутта ...
Я не знаю таких "страшных" слов, не довелось в свое время узнать. Да и алгоритмов решения того, что скрыто в этих "страшных" словах тоже не знаю. Закатив глазки
Зато мне нравится "оформление" класса и подход к реализации.
Но есть вопрос: А где же всетаки может такая штука пригодиться, например мне.
(просто интересно пощупать и разобраться в алгоритмах, а использовать негде)
 
 Top
EuGen Администратор
Отправлено: 22 Января, 2013 - 14:45:00
Post Id


Профессионал


Покинул форум
Сообщений всего: 9097
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




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

В вебе, наверное, этого не нужно будет делать. По крайней мере с ходу задача в голове не возникает (ровно как она не возникла за долгие годы работы). Однако же, как и в случае с, например, выложенным в этой же ветке, но в соседней теме "Конверторе диапазонов", решение носит больше аналитический характер и удовлетворяет мой академический интерес.

Насчет оформления - есть некоторые элементы, которые были "доделаны второпях" (например, у метода вывода уравнения для печати значения по-умолчанию для аргументов заданы прямо в объявлении, вместо того, чтобы быть сделанными как константы, как это есть в остальных местах класса). Кроме того, я "сэкономил" на вызове исключений (к примеру, при проверке внутри метода решения я опираюсь на то, что старший коэффициент всегда отличен от нуля, но, строго говоря, метод этого знать не может и не должен, а я же - знаю, так как фильтрую коэффициенты и степень уравнения в конструкторе). Уверен, видя достаточно высокую громоздкость вычислений, читатели простят мне такие оплошности.

DeepVarvar
Если Вам это интересно, то вкратце ситуация обрисована в:
Формула Кардано для решения кубического уравнения
Метод Виета для тригонометрического получения корней кубического уравнения
Метод Феррари для решения уравнения 4-й степени при помощи получения резольвенты с последующим её разрешением.
Теорема Абеля-Руфини, утверждающая, что уравнение степени N не имеет выразимых в радикалах корней при N>4 в общем случае, и опирающаяся на теорию групп Галуа


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
DeepVarvar Супермодератор
Отправлено: 22 Января, 2013 - 14:58:12
Post Id



Активный участник


Покинул форум
Сообщений всего: 10378
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


Помог: 353 раз(а)




EuGen пишет:
В вебе, наверное, этого не нужно будет делать
Жаль...
EuGen пишет:
я "сэкономил" на вызове исключений
Я тоже всегда на оных экономлю, правда не в тех местах где проверяются входные данные.
EuGen пишет:
вместо того, чтобы быть сделанными как константы
А они подразумевают возможность "настройки", или это просто дань "моде", вынести что-то в константы класса?

Эхх, пойду хоть почитаю про все эти "страшные" слова...
 
 Top
EuGen Администратор
Отправлено: 22 Января, 2013 - 15:05:06
Post Id


Профессионал


Покинул форум
Сообщений всего: 9097
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




DeepVarvar пишет:
А они подразумевают возможность "настройки", или это просто дань "моде", вынести что-то в константы класса?

Конечно. Возможно, Вы захотите изменить логику функции и подставлять не z, а x - а степень выводить при помощи <sup>..</sup> - класс ведь может использоваться и на веб-страницах. Правда, для последнего придется немного адаптировать вывод (повторюсь, этот метод дописывался немного "впопыхах"), но тем не менее - идея в этом.
DeepVarvar пишет:
Эхх, пойду хоть почитаю про все эти "страшные" слова...

Это вовсе не обязательно ввиду
EuGen пишет:
В вебе, наверное, этого не нужно будет делать

- так что стоит почитать, только если в самом деле интересно. Здесь затрагиваются вопросы высшей алгебры, теории комплексных чисел, дискретного и функционального исчислений, так что "разобраться во всем" - значит получить математическое образование, на что могут уйти годы. Это вовсе не обязательно и никак не влияет на профессионализм веб-разработчика.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
DeepVarvar Супермодератор
Отправлено: 22 Января, 2013 - 15:06:59
Post Id



Активный участник


Покинул форум
Сообщений всего: 10378
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


Помог: 353 раз(а)




EuGen пишет:
Это вовсе не обязательно и никак не влияет на профессионализм веб-разработчика
Я считаю что влияет и как-то мне стыдновато Хм
 
 Top
caballero
Отправлено: 22 Января, 2013 - 15:17:41
Post Id


Активный участник


Покинул форум
Сообщений всего: 6001
Дата рег-ции: Сент. 2011  
Откуда: Харьков


Помог: 126 раз(а)




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


-----
Бесплатная система складского учета с открытым кодом https://zippy[dot]com[dot]ua/zstore
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 1 (гостей: 1, зарегистрированных: 0)
« Пользовательские функции »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB