pianoforte Skrevet 29. august 2006 Del Skrevet 29. august 2006 Finnes det noe open-source kalkulator-skript/klasse for PHP som fungerer omtrent som Calc? Det vil si at jeg ønsker en slags "kommandolinjekalkulator", hvor man skriver inn et regnestykke (f eks "(215.3-64)/27*(78.1*(299-2))/1-2") og få resultatet. Har begynt å skrive et skript, men vet ikke om jeg har tid og får til å fullføre det. Lenke til kommentar
Martin A. Skrevet 29. august 2006 Del Skrevet 29. august 2006 echo() kan utføre matematiske utregninger. <?php echo 2 + 2 *2; ?> Dette vil da bli 8. Hvordan den ser på paranteser vet jeg ikke. Lenke til kommentar
Ernie Skrevet 29. august 2006 Del Skrevet 29. august 2006 (endret) Finnes helt sikkert script der ute som regner ut infix-uttrykk, men det er relativt lett å lage det selv også da. Straks du får gjort det om til postfix så er det jo basic stack-operasjoner for å regne det ut. Akkurat nå kjeder jeg meg en smule så har ingenting imot å lage det Endret 29. august 2006 av Ernie Lenke til kommentar
pianoforte Skrevet 29. august 2006 Forfatter Del Skrevet 29. august 2006 Ernie: Har aldri hørt om infix og postfix (i denne sammenhengen), men etter å ha søkt litt på nettet, ser det ut til at jeg vil sette meg litt inn i det og prøve å lage noe selv. Lenke til kommentar
Ernie Skrevet 29. august 2006 Del Skrevet 29. august 2006 (endret) Okey Sitter selv og knoter med det her, og det er visst ikke like trivielt som jeg trodde. Å regne ut et postfix-uttryk er enkelt. Å konvertere et infix-uttryk til postfix er derimot ikke fult så enkelt. Dog, i teorien skal det være mulig å regne ut infix-uttryk direkte, men det er overhode ikke enkelt. Forøvrig, hvis du ikke veit det er infix måten vi mennesker skriver opp regnestykk. Postfix kan du lese mer om her siden jeg ikke klarer å forklare det enkelt (involverer datastrukturen tre og traverseringen av det, noe jeg har en følelse av at du ikke veit helt hva er) Endret 29. august 2006 av Ernie Lenke til kommentar
pianoforte Skrevet 29. august 2006 Forfatter Del Skrevet 29. august 2006 Leser denne artikkelen nå, og det ser ut til å være ganske komplisert, ja. Men i tilfelle jeg får til å konvertere fra infix til postfix, hvordan regner jeg ut et postfix-uttrykk? Hvordan gjør andre matematikkprogrammer (Mathematica, Maple, calc, bc osv.) det? Regner de ut infix-uttrykket direkte, eller går de også veien om postfix? Eller finnes det andre metoder? Lenke til kommentar
Ernie Skrevet 29. august 2006 Del Skrevet 29. august 2006 (endret) Jøss ... Jeg tror trekker tilbake at det her var lett. Infix -> prefix var en hard nøtt gitt Uannsett, vil nesten anta at man bruker den algoritmen du linket til, bare sliter litt med å implementere den i PHP Edit: Baaaah Ser feilen nå, men jeg hater PHPs elendige utvalg av datastrukturer. Struct hadde vært noe, men får vel nøye meg med array. Endret 29. august 2006 av Ernie Lenke til kommentar
Ernie Skrevet 29. august 2006 Del Skrevet 29. august 2006 (endret) Weee ... endelig fikk jeg det til å funke Så lenge input er uten snarveier i skrivemåten (f.eks 3(2+1)) skal det funke. Jeg har ikke giddet å kommentere koden (ja, fyyyyy meg). Mulig jeg gjør det når jeg er litt mindre trøtt. //Infix: 5 + ((1 + 2) * 4) + 3 //Postfix: 5 1 2 + 4 * + 3 + echo CalculateInfix("5 + ((1 + 2) * 4) + 3"); function CalculateInfix($infix) { $stack = array('#'); $valid_op = array('-', '+', '*', '/', '^', '(', ')'); $mp = 1; $temp = $temp2 = $postfix = ''; $i = $j = 0; $size = strlen($infix); while ($i < $size) { if (is_numeric($infix[$i])) do $temp .= $infix[$i++]; while (is_numeric($temp.$infix[$i]) && $i < $size); else $temp = $infix[$i++]; if (in_array($temp, $valid_op) || is_numeric($temp)) { if (SetValue($temp, 1) > $stack[count($stack)-1][0]) array_push($stack, array(SetValue($temp, 2)*$mp, $temp)); else { while (SetValue($temp, 1)*$mp <= $stack[count($stack)-1][0]) { list(, $temp2) = array_pop($stack); if ($temp2 != '(' && $temp2 != ')') $postfix[$j++] = $temp2; elseif ($temp2 == ')') $mp /= 10; elseif ($temp2 == '(') $mp *= 10; } array_push($stack, array(SetValue($temp, 2)*$mp, $temp)); } } $temp = ''; } while ($stack[count($stack)-1] != '#') list(, $postfix[$j++]) = array_pop($stack); $stack = array(); for ($i = 0; $i < $j; $i++) { if (is_numeric($postfix[$i])) array_push($stack, $postfix[$i]); else { $num1 = array_pop($stack); $num2 = array_pop($stack); switch ($postfix[$i]) { case '*': array_push($stack, $num2 * $num1); break; case '/': array_push($stack, $num2 / $num1); break; case '-': array_push($stack, $num2 - $num1); break; case '+': array_push($stack, $num2 + $num1); break; case '^': array_push($stack, $num2 ^ $num1); break; } } } return array_pop($stack); } function SetValue($input, $type) { $add = array('-', '+'); $multi = array('*', '/'); if ($input == '#') return 0; elseif (in_array($input, $add)) return 3; elseif (in_array($input, $multi)) return 4; elseif ($input == '^') return 5; elseif (is_numeric($input)) return 9; elseif (($input =='(' && $type == 1) || ($input ==')' && $type == 2)) return 9; else return 2; } Edit: Bare så det er sagt: Ja, det er nok et potensial for optimalisering Endret 29. august 2006 av Ernie Lenke til kommentar
pianoforte Skrevet 30. august 2006 Forfatter Del Skrevet 30. august 2006 Ser bra ut. Men den sliter litt med negative tall. Det kan løses ved å sette en "0" foran det negative tallet, men det er jo litt tungvindt... F eks: 2*-2 eller 2*(-2) fungerer ikke, men 2*(0-2) fungerer. (Jeg har selv skrevet et skript som regner ut infix-uttrykk direkte, og da var det dette med negative tall som gjorde at jeg ikke kom noe videre.) I tillegg sliter den når det er en parentes på slutten av et uttrykk, f eks "2*(3+4)". Dette kan løses ved å legge til "*1" på slutten, men det er jo også litt tungvindt. Lenke til kommentar
Ernie Skrevet 30. august 2006 Del Skrevet 30. august 2006 (endret) Hmm ... det her var litt mer komplisert Jeg tror nesten jeg må skrive hele greia om når jeg kommer hjem. Å regne det ut direkte ble plutselig mindre komplisert. Det jeg tenker meg ut her blir å hente ut mellom ( og motsående ) og erstatte det med et tall v.hj.a rekursjon. Problemområdet blir rett og slett def. av tall. Finnes endel string-funksjoner som funker fett til det her (substr_replace, substr, strpos). Endret 30. august 2006 av Ernie Lenke til kommentar
kakkle Skrevet 30. august 2006 Del Skrevet 30. august 2006 (endret) Hva med denne lille "skumle" snutten, da ? <? $regnestykke = "(215.3-64)/27*(78.1*(299-2))/1-2"; eval("\$resultat = ".$regnestykke.";"); echo $regnestykke." = ".$resultat; ?> Takler ihvertfall parenteser greit . Men dòg så er det jo ikke anbefalt å bruke eval, da... Koden gir dette i output: (215.3-64)/27*(78.1*(299-2))/1-2 = 129979.83 Stemmer kanskje ? Har ikke fått sjekket det så veldig nøye... Dersom input fra bruker brukes, må det valideres nøye (Bare lov med tall og operatorer f.eks...) Endret 30. august 2006 av kakkle Lenke til kommentar
Ernie Skrevet 30. august 2006 Del Skrevet 30. august 2006 nå er det snakk om brukerinput her da, og jeg ville iallfall aldri i verden sendt brukerinput inn i eval. Det er det samme som å be om bråk. Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå