Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

StrCalc - Rechnen mit Strings [Punkt vor Strich, Klammern, Potenzen, ...]


  • Please log in to reply
2 replies to this topic
SAPlayer
  • Members
  • 403 posts
  • Last active: Apr 11 2014 04:45 PM
  • Joined: 06 Nov 2012

Ich habe für mein Projekt mal wieder keine Mühen gescheut und habe eine PHP-Funktion zum Rechnen mit Strings in AHK übersetzt.

Die PHP-Funktion ist nicht von mir, ich habe sie aus diesem Forum: Thread in externem Forum [Rechnen mit Strings]

Ich habe sie nach AHK übersetzt und sogar überarbeitet, sodass sie auch (hoffentlich) nach dem Punkt-vor-Strich-System arbeitet:

StrCalc(str){ ;http://www.php.de/php-tipps-2010/66855-mathematische-berechnung-vom-stringinhalt.html#post507927
	stack := Object()
	v := Object()
	m := Object()
	v[0] := v[1] := op := ""
	pos := 0
	str := RegExReplace(RegExReplace(str, "\s"), "\d+[*/]\d+", "($0)")
	while(pos := RegExMatch(str, "([()+*/^-]|(\-?\d+))", regex, pos + (StrLen(regex1) ? StrLen(regex1) : 1)))
		m.Insert(regex1)
	for i, tk in m
	{
		if(tk = "+" OR tk = "-" OR tk = "*" OR tk = "/" OR tk = "^"){
			op := tk
			continue
		}
		else if(tk = "("){
			stack.Insert([v[0], v[1], op])
			v[0] := v[1] := op := ""
			continue
		}
		else if(tk = ")"){
			kResult := v[0]
			v[0] := stack[stack._maxIndex(), 1]
			v[1] := stack[stack._maxIndex(), 2]
			op := stack[stack._maxIndex(), 3]
			stack.Remove()
			v[(v[0] = "") ? 0 : 1] := kResult
			bracketMode := 1
		}
		if(!bracketMode)
			v[((op = "") && (v[0] = "")) ? 0 : 1] := tk
		if(v[1] != ""){
			if(op = "^")
				v[0] := v[0] ** v[1]
			else
				v[0] := ((op = "+") * (v[0] + v[1])) + ((op = "*") * (v[0] * v[1])) + ((op = "/") * (v[0] / v[1])) + ((op = "-") * (v[0] - v[1]))
			op := v[1] := ""
		}
		bracketMode := 0
	}
	return v[0]
}

Normalerweise sollten alle normalen Rechenarten (+-*/), Klammern, Potenzen (^) und Punkt-vor-Strich-System funktionieren.

Das habe ich jetzt des Öfteren getestet, ich garantiere allerdings keine Richtigkeit der Ergebnisse.

Ein Aufruf sieht zum Beispiel so aus:

MsgBox, % StrCalc("10 + 20") ;30, die Leerzeichen werden ignoriert
MsgBox, % StrCalc("10^3") ;1000
MsgBox, % StrCalc("20+30*10") ;320, wegen Punkt vor Strich
MsgBox, % StrCalc("(20+30)*10") ;500

Geplant:

  • Potenz vor Punkt
  • Prozent akzeptieren (z.B. "1000*10%" = 100)

Ich hoffe, dass euch das ein wenig weiterhilft

SAPlayer



Bentschi
  • Moderators
  • 120 posts
  • Last active: Sep 05 2014 02:12 AM
  • Joined: 26 Nov 2008
eval(e, byref log=0)
{
  global eval_vars
  static vars := {"(pi|π)":3.14159265, "e":2.71828182, "log2e":1.44269504, "log10e":0.43429448
  , "ln2":0.69314718, "ln10":2.30258509, "sqrt2":1.41421356, "euler":0.57721566, "true":1, "false":0, "null":0
  , "(answer.?to.?|)life,?.?the.?universe.?and.?everything":42, "number.?of.?horns.?on.?a.?unicorn":1}
  static ahk_vars := ["A_WorkingDir", "A_ScriptDir", "A_ScriptName", "A_ScriptFullPath", "A_AhkVersion", "A_AhkPath", "A_IsUnicode"
  , "A_IsCompiled", "A_YYYY", "A_MM", "A_DD", "A_MMMM", "A_MMM", "A_DDDD", "A_DDD", "A_WDay", "A_YDay", "A_YWeek", "A_Hour"
  , "A_Min", "A_Sec", "A_MSec", "A_Now", "A_NowUTC", "A_TickCount", "ComSpec", "A_Temp", "A_OSType", "A_OSVersion"
  , "A_PtrSize", "A_Language", "A_ComputerName", "A_WinDir", "A_ProgramFiles", "A_AppData", "A_AppDataCommon", "A_Desktop"
  , "A_DesktopCommon", "A_StartMenu", "A_StartMenuCommon", "A_Programs", "A_ProgramsCommon", "A_Startup", "A_StartupCommon"
  , "A_MyDocuments", "A_IsAdmin", "A_ScreenWidth", "A_ScreenHeight", "A_IPAddress1", "A_IPAddress2", "A_IPAddress3"
  , "A_IPAddress4", "A_Cursor", "Clipboard", "ClipboardAll"]
  static build_in_funcs := ["hex", "deg2rad", "rad2deg", "min", "max", "clamp"]
  static num := "(__str[0-9]+_|-?0x[0-9a-fA-F]+|-?[0-9]*\.?[0-9]+)"
  static hex := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f"]
  static b := hex.minIndex()
  static str := []
  global_vars := (isobject(eval_vars)) ? eval_vars : []
  if (e[b]="clr")
  {
    while (regexmatch(e[b+1], t := "(__str[0-9]+_|[,²²*~/%+\-<>&^|=!&?:]|-?0x[0-9a-fA-F]+|-?[0-9]*\.?[0-9]+)", m))
    {
      x .= m1
      e[b+1] := regexreplace(e[b+1], t "(.*)", "$2")
    }
    return x
  }
  if (e[b]="trim")
    return regexreplace(regexreplace(regexreplace(e[b+1], ",\s*\+\s*", ","), "^\s*\+\s*"), "\s*([+\-])\s*\+\s*", "$1")
  if (e[b]="str")
  {
    while (regexmatch(e[b+1], "__str([0-9]+)_", m))
      e[b+1] := regexreplace(e[b+1], "__str[0-9]+_(.*)", e[b+2] str[m1] e[b+2] "$1")
    return e[b+1]
  }
  if (e[b]="hex")
  {
    Loop, 16
      h := hex[((e[b+1]>>((A_Index-1)*4))&0xf)+b] h
    return (h="") ? "" : "0x" ((regexreplace(h, "^0*")="") ? "0" : regexreplace(h, "^0*"))
  }
  if (e[b]="deg2rad")
    return e[b+1]*0.01745329
  if (e[b]="rad2deg")
    return e[b+1]*57.29578
  if (e[b]="min")
    return (e[b+1]>e[b+2]) ? e[b+2] : e[b+1]
  if (e[b]="max")
    return (e[b+1]>e[b+2]) ? e[b+1] : e[b+2]
  if (e[b]="clamp") ;value, min, max
    return (e[b+1]<e[b+2]) ? e[b+2] : ((e[b+1]>e[b+3]) ? e[b+3] : e[b+1])
  if (e[b]="var")
  {
    if (e[b+1]="")
      return
    if (regexmatch(e[b+1], "^" num "$"))
      return e[b+1]
    str.insert(e[b+1])
    return "__str" str.maxIndex() "_"
  }
  if (regexmatch(e, "^\s*(.*?)\s*$", m))
    e := regexreplace(m1, "\s", " ")
  log := [eval(["str",e,""""])]
  if (regexmatch(e, """([^""]*)"""))
    str := []
  while (regexmatch(e, """(?P<str>(""""|[^""]*)*)""", m))
  {
    str.insert(regexreplace(mstr, """""", """"))
    e := regexreplace(e, """((""""|[^""]*)*)""(?P<end>.*)", "__str" str.maxIndex() "_${end}")
  }
  while (regexmatch(e, "([+\-]\s*[+\-])", m))
  {
    e := regexreplace(e, "-\s*-", "+")
    e := regexreplace(e, "\+\s*-", "-")
    e := regexreplace(e, "([+\-])\s*\+", "$1")
  }
  for k,v in global_vars
  {
    while (regexmatch(e, "iO)(^|[^a-zA-Z0-9_])" k "([^a-zA-Z0-9_]|$)", m))
      e := regexreplace(e, "i)(^|[^a-zA-Z0-9_])" k "(?P<p>[^a-zA-Z0-9_]|$)", "$1" eval(["var", v]) "${p}")
  }
  for k,v in vars
  {
    while (regexmatch(e, "iO)(^|[^a-zA-Z0-9_])" k "([^a-zA-Z0-9_]|$)", m))
      e := regexreplace(e, "i)(^|[^a-zA-Z0-9_])" k "(?P<p>[^a-zA-Z0-9_]|$)", "$1" eval(["var", v]) "${p}")
  }
  for i,k in ahk_vars
  {
    while (regexmatch(e, "i)(^|[^a-zA-Z0-9_])" k "([^a-zA-Z0-9_]|$)", m))
      e := regexreplace(e, "i)(^|[^a-zA-Z0-9_])" k "([^a-zA-Z0-9_]|$)", "$1" eval(["var", %k%]) "$2")
  }
  if (log[log.maxIndex()] != eval(["str",e,""""]))
    log.insert(eval(["str",e,""""]))
  while (regexmatch(e, "(.*)\(([^)]*)\)(.*)", m))
  {
    s := 0, le := eval(m2, l), p := []
    Loop, parse, le, `,, % " "
      p.insert(eval(["str",A_LoopField]))
    if (regexmatch(m1, "([a-zA-Z0-9_]+)$", fn))
    {
      if (isfunc(fn1))
        r := func(fn1).(p*), s := 1
      else
      {
        for k,v in build_in_funcs
        {
          if (v=fn1)
            r := eval([fn1,p*]), s := 1
        }
      }
      e := (s) ? substr(m1, 1, -strlen(fn1)) eval(["var", r]) m3 : m1 le m3
    }
    else
      e := m1 le m3
    for k,v in l
    {
      if (log[log.maxIndex()] != eval(["str", m1 fn1 "(" v ")" m3, """"]))
        log.insert(eval(["str", m1 fn1 "(" v ")" m3, """"]))
    }
    if (log[log.maxIndex()] != eval(["str",e,""""]))
      log.insert(eval(["str",e,""""]))
  }
  e := eval(["clr", e])
  while (regexmatch(e, "(.*?)" num "\s*(²|³)\s*(.*)", m)) ; ² ³
    log.insert(eval(["str",e := eval(["trim",eval(["str",m1]) "+" (m2 ** ((m3="²") ? 2 : 3)) m4]),""""]))
  while (regexmatch(e, "(.*?)" num "\s*\*\*\s*" num "(.*)", m)) ; **
    log.insert(eval(["str",e := eval(["trim",m1 "+" (eval(["str",m2]) ** eval(["str",m3])) m4]),""""]))
  while (regexmatch(e, "(.*?)" num "\s*~\s*" num "(.*)", m)) ; ~
    log.insert(eval(["str",e := eval(["trim",m1 "+" (eval(["str",m2]) ~ eval(["str",m3])) m4]),""""]))
  while (regexmatch(e, "(.*?)" num "\s*(\*|/|//|%)\s*" num "(.*)", m)) ; * / // %
    log.insert(eval(["str",e := eval(["trim",m1 "+" ((m3="*" || m3="/") ? ((m3="*") ? eval(["str",m2]) * eval(["str",m4]) : eval(["str",m2]) / eval(["str",m4])) : ((m3="//") ? eval(["str",m2]) // eval(["str",m4]) : mod(eval(["str",m2]), eval(["str",m4])))) m5]),""""]))
  while (regexmatch(e, "(.*?)" num "\s*(\+|-)\s*" num "(.*)", m)) ; + -
    log.insert(eval(["str",e := eval(["trim",m1 "+" ((m3="+") ? eval(["str",m2]) + eval(["str",m4]) : eval(["str",m2]) - eval(["str",m4])) m5]),""""]))
  while (regexmatch(e, "(.*?)" num "\s*(<<|>>)\s*" num "(.*)", m)) ; << >>
    log.insert(eval(["str",e := eval(["trim",m1 "+" ((m3="<<") ? eval(["str",m2]) << eval(["str",m4]) : eval(["str",m2]) >> eval(["str",m4])) m5]),""""]))
  while (regexmatch(e, "(.*?)" num "\s*(&|^|\|)\s*" num "(.*)", m)) ; & ^ |
    log.insert(eval(["str",e := eval(["trim",m1 "+" ((m3="&") ? eval(["str",m2]) & eval(["str",m4]) : ((m3="^") ? eval(["str",m2]) ^ eval(["str",m4]) : eval(["str",m2]) | eval(["str",m4]))) m5]),""""]))
  while (regexmatch(e, "(.*?)" num "\s*(>|<|>=|<=)\s*" num "(.*)", m)) ; > < >= <=
    log.insert(eval(["str",e := eval(["trim",m1 "+" ((m3=">" || m3=">=") ? ((m3=">") ? (eval(["str",m2])>eval(["str",m4])) : (eval(["str",m2])>=eval(["str",m4]))) : ((m3="<") ? (eval(["str",m2])<eval(["str",m4])) : (eval(["str",m2])<=eval(["str",m4])))) m5]),""""]))
  while (regexmatch(e, "(.*?)" num "\s*(=|==|<>|!=)\s*" num "(.*)", m)) ; = == <> !=
    log.insert(eval(["str",e := eval(["trim",m1 "+" ((m3="=" || m3="==") ? ((m3="=") ? (eval(["str",m2])=eval(["str",m4])) : (eval(["str",m2])==eval(["str",m4]))) : ((m3="<>") ? (eval(["str",m2])<>eval(["str",m4])) : (eval(["str",m2])!=eval(["str",m4])))) m5]),""""]))
  while (regexmatch(e, "i)(.*?)(!|not)\s*(.*)", m)) ; ! not
    log.insert(eval(["str",e := eval(["trim",m1 (!(eval(["str",m3])))]),""""]))
  while (regexmatch(e, "i)(.*?)" num "\s*(&&|and)\s*" num "(.*)", m)) ; && and
    log.insert(eval(["str",e := eval(["trim",m1 "+" (eval(["str",m2]) && eval(["str",m4])) m5]),""""]))
  while (regexmatch(e, "i)(.*?)" num "\s*(\|\||or)\s*" num "(.*)", m)) ; || or
    log.insert(eval(["str",e := eval(["trim",m1 "+" (eval(["str",m2]) || eval(["str",m4])) m5]),""""]))
  while (regexmatch(e, "\s*(.+?)\s*\?\s*(.+?)\s*:\s*(.+)\s*", m)) ; ?:
    log.insert(eval(["str",e := eval(["trim",eval(["str",m1]) ? m2 : m3]),""""]))
  e := eval(["str",eval(["clr", e])])
  if (log[log.maxIndex()] != e)
    log.insert(e "")
  return e ""
}


SAPlayer
  • Members
  • 403 posts
  • Last active: Apr 11 2014 04:45 PM
  • Joined: 06 Nov 2012
Ich kenne auch eval, aber die Funktion war mir ganz ehrlich zu lang xD
Oder kann man die evtl. auf Mathe-Funktionen kürzen?