...

View Full Version : caret (^) to pow() function



djh101
02-28-2012, 09:32 AM
Having to work with derivatives a lot, I made this nice, simple function for converting a^b form exponents in strings to eval'able pow(a,b) form. Enjoy. :)


function carToPow($expression){
//array of positions: start of base, position of ^, end of power
$pos = array(null,null,null);
//array of parts: base and power
$parts = array();

for($i=0; $i<strlen($expression); $i++){

if($expression[$i] === '^'){
$pos[1] = $i;

//scan for base
if($expression[$i-1] === ')'){ //base is a function
$depth = 0;
for($j=$i-1; $j >= 0; $j--){
if($expression[$j] === ')') $depth++;
if($expression[$j] === '(') $depth--;
if($depth == 0){
$pos[0] = $j;
$parts[0] = substr($expression, $j, $i-$j);
break;
}
}
} else if($expression[$i-1] === 'x'){ //base is a variable
$pos[0] = $i-1;
$parts[0] = "x";
} else { //base is a number
if(preg_match("/\\d*\\.{0,1}\\d+\\^/",$expression,$foo)){
$pos[0] = $i - strlen($foo[0]) + 1;
$parts[0] = substr($foo[0],0,strlen($foo[0])-1);
} else return false;
}

//scan for power
if($expression[$i+1] === '('){ //power is a function
$depth = 0;
for($j=$i+1; $j < strlen($expression); $j++){
if($expression[$j] === '(') $depth++;
if($expression[$j] === ')') $depth--;
if($depth == 0){
$pos[2] = $j;
$parts[1] = substr($expression, $i+1, $j-$i);
break;
}
}
} else if($expression[$i+1] === 'x'){ //base is a variable
$pos[2] = $i+1;
$parts[1] = "x";
} else { //power is a number
if(preg_match("/\\^\\d*\\.{0,1}\\d+/",$expression,$foo)){
$pos[2] = $i + strlen($foo[0]) - 1;
$parts[1] = substr($foo[0],1,strlen($foo[0])-1);
} else return false;
}

if($parts[0] == null || $parts[1] == null) return false;
$expression = substr($expression,0,$pos[0]).'pow('.$parts[0].','.$parts[1].')'.substr($expression,$pos[2]+1,strlen($expression)-$pos[2]);
return ($expression = carToPow($expression)) ? $expression : false;

}

}
return $expression;

}

Fou-Lu
02-28-2012, 02:47 PM
I don't know if I'd recommend that the caret be replaced since you'll lose the concept of the xor, but why not just use a regex to match it completely?


$sEquation = '452.2 ^ x + 14 - y';

$sPattern = '/([a-z]|\d+(?:\.\d+)?)*\s*\^\s*([a-z]|\d+(?:\.\d+)?)/i';
$sReplace = 'pow($1, $2)';

$sResult = preg_replace($sPattern, $sReplace, $sEquation);

print $sResult;

That will give you the same result. Granted without using a stack for this, the behaviour becomes slightly unusual if you provide an unmarked multiplication.

djh101
02-28-2012, 07:23 PM
This is intended for strings of standard math functions, where ^ is used for exponential expressions (and xor is not used at all). Your code works fine for standard a^b expressions, but the stack is needed for converting functions where the base or exponent is a parenthetical expression.

Fou-Lu
02-28-2012, 09:22 PM
Ooh yeah I do see what you mean, never thought about parenthetical expressions for the exponent, and its a mess if you have pow of pow (...of pow...*).
I know this can be done in regex as well, but I'm afraid that's beyond my skills as a matcher for sure. Stack handling even iterating is probably faster than the pattern would be anyway.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum