Страницы: 1
RSS
Работа с комплексными числами в Excel (VBA макрос)
 
Стандартное решение мне очень сильно не нравиться. мним.множ, мним.дел и т.п. - операции можно производить только попарно, запись неудобная и т.д.    
я хочу иметь возможность оперировать с комплексными числами так же как с обычными. ну или возможно близко к этому :)    
решение вижу таким: делается пользовательская функция, которой передается формула в виде строки. т.е в ячейке будет запись =ком("B2+B3")  
где "ком" имя моей функции. формула в скобках произвольная формула в том числе с комплексными числами. например такая  
((B3+B4)*B6+B6*B9)*2  
путем нехитрых манипуляций можно получить строкове значение этого выражения  
(((2,5+0,156i)+(752+5,6i))•0,254+0,254•(0,53+i7,54))•2  
(как в скобки брать все комлексные числа только помучаться еще надо :). теперь собственно вопрос как получить результат такого строкового выражения ? задача то с одной стороны стандартная... на python например решает в два клика. но какими средствами это можно под офис решить ? как реализовать функцию для вычисления строкового выражения содержащего комплексные числа ?
 
Можете объяснить все это менее сумбурно?    
Например, пример решения на Python.  
Пример решение в Excel.  
Что хотите получить в VBA.  
Не все помнят, что такое комплексные числа.
 
Про комплексные числа http://www.planetaexcel.ru/forum.php?thread_id=6558
 
В надстройке XNUMBERS.XLA есть функции ячеек для работы с комплексными числами.  
В частности, там есть функция =cplxeval( Formula;[Var1; Var2 …] )
 
Например, пусть в A1:A2 числами записаны действительная (A1) и мнимая (A2)части  комплексного числа X, а в B1:B2 соответственно - действительная и мнимая части комплексного числа Y.  
 
Тогда, если выделить, например C1:C2, записать формулу:  
=cplxeval("x+y";A1:A2;B1:B2)  
и нажать Ctrl-Shift-Enter, то в C1 будет записана действительная часть результата, а в C2 – мнимая часть результата.  
 
Надстройка поддерживает 52 функции для работы с комплексными числами.  
Упоминается в копилке идей: http://www.planetaexcel.ru/forum.php?thread_id=11486  
Прямая ссылка на скачивание: http://digilander.libero.it/foxes/xnumb56.zip
 
ZVI  
ВЕСЧ! не ожидал такое встретить под vba. задачу из заголовка решает легко.    
судя по функционалу умеет и еще много всего вкусного. пошел изучать :)    
http://www.thetropicalevents.com/Xnumbers60.htm  
 
"Сайт активно развивался, но, к сожалению, в декабре 2007г. Леонардо принял решение завершить развитие этого проекта. Реальных причин я не знаю, а спрашивать не этично."  
гугл подсказал что есть и продолжение :)    
http://www.thetropicalevents.com/Xnumbers60.htm
 
в принципе почти разобрался. остался вопрос удобства использования.    
предположим что моя функция называет "ком". теперь вопрос как наиболее удобно ввести формулу  
я могу записать в ячейку  
=ком("A2+B4") получить для работы строку формулы. непонятно таким образом как получить адрес ячейки из которой запущена формула.    
можно записать в ячейке A3 формулу =A2+B4  
а ячейкой ниже =ком(A3), тогда я передам ячейку как range и смогу узнать имя листа, номер ячейки.    
а вот как организовать фукнцию чтобы писать просто    
=ком(A2+B4)  
и получать для вычисления как выражение A2+B4 так и имя листа, адрес ячейки ?
 
В примере надстройки, который  приводил  =cplxeval("x+y";A1:A2;B1:B2) анализируется "x+y" и вместо X и Y подставляются соответствующие значения из A1:A2 и B1:B2. Это так называемый парсинг текстовой формулы - дело, в общем случае, не простое.  
 
А чтобы получить адрес ячейки, вызывающей UDF, или формулу внутри скобок из этой ячейки, можно использовать такие UDF:  
 
Function MyFuncAddress(Optional Expr)  
 MyFuncAddress = Application.ThisCell.Address(0, 0)  
End Function  
 
Function MyFuncFormula(Optional Expr)  
 MyFuncFormula = Application.ThisCell.Formula  
 MyFuncFormula = Mid(MyFuncFormula, Len("MyFuncFormula") + 2)  
End Function  
 
Введите в ячейки такие формулы и посмотрите, что получится:  
=MyFuncAddress(A1+B1)  
=MyFuncFormula(A1+B1)
 
спасибо. все получилось. остально чуть-чуть доработать напильником в сторону обработки любых форм комплексного числа :)  
Вот чего наклепал  
Function eval(Optional Expr) As String  
 
  Set c = Application.ThisCell  
     
  sSheetName = c.Parent.Name  
     
  s = c.Formula  
  Set oRegExp = CreateObject("VBscript.Regexp")  
     
  'получаем само выражение  
  Debug.Print s  
  token = "eval\((.+)\)"  
   
     With oRegExp  
       .Global = True  
       .ignorecase = True  
       .MultiLine = False  
       'Поскольку теперь все ссылки абсолютные, то знак доллара будет обязательно!  добавляем имя листа  
       .Pattern = token  
       s = .Replace(s, "$1")  
     End With  
       
   Debug.Print s  
 
     
   s = Application.ConvertFormula(s, xlA1, xlA1, True) 'вычисл. формула  
   Debug.Print s  
 
     With oRegExp  
       .Global = True  
       .ignorecase = True  
       .MultiLine = False  
       'Поскольку теперь все ссылки абсолютные, то знак доллара будет обязательно!  добавляем имя листа  
       .Pattern = "([^\!])(\$[a-z]+\$[0-9]+)"
       s = .Replace(s, "$1" & sSheetName & "!$2")  
     End With  
 
s = Replace(s, "=", "")  
     
Debug.Print s  
 
 
       token = "(\'?[\w\d]+\'?\!\$\w\w?\$\d+)"
           
      'находим ссылки на ячейки  
       If True Then  
         With oRegExp  
           .Global = True  
           .ignorecase = True  
           .MultiLine = False  
           'Поскольку теперь все ссылки абсолютные, то знак доллара будет обязательно!  добавляем имя листа  
           .Pattern = token  
           s = .Replace(s, """ & $& & """)  
           Debug.Print s  
         End With  
       End If  
 
     
       
Debug.Print s  
 
s = Evaluate("=""" & s & """")  
Debug.Print s  
 
s = Replace(s, "i", "j")  
s = Replace(s, ".", ",")  
 
        tokenReList = Array( _  
           Array("var", "(\'?[\w\d]+\'?\!\$\w\w?\$\d+)") _
           )  
           
 
   For Each token In tokenReList  
       '('[^'\r\n]'!)?(\$[A-Z]+\$[0-9]+)
       'находим ссылки на ячейки  
       If True Then  
         With oRegExp  
           .Global = True  
           .ignorecase = True  
           .MultiLine = False  
           'Поскольку теперь все ссылки абсолютные, то знак доллара будет обязательно!  добавляем имя листа  
           .Pattern = token(1) '"(([^\r\n\+\*\(\)/-])*\!)?(\$[A-Z]+\$[0-9]+)"
           s = .Replace(s, """ & $& & """)  
           Debug.Print s  
         End With  
       End If  
   Next token  
     
Debug.Print s  
r = cplxeval(s)  
Debug.Print r(1) & " + j" & r(2)  
eval = r(1) & " + j" & r(2)  
 
End Function
Страницы: 1
Наверх