As Alex says, the ^ operator does not perform exponentiation in perl, but it does perform exponentiation in formulas in pg. By putting the expression in quotes you are storing it as a string which is then evaluated by the answer checker as a mathematical formula, so it recognizes ^ as exponentiation.
Perhaps some simplified examples will make this clearer.
$a = 3;
$b = $a^2;
# The value of $b will be 6, since perl treats ^ as XOR.
$c = $a**2;
# The value of $c will be 9 (3 raised to the power of 2)
$d = "$a^2";
# The value of $c will be the string "3^2".
$e = "$a**2";
# The value of $c will be the string "3**2".
Things get more complicated when you then pass these variables to an answer checker. Since the values of $b and $c are numbers, WeBWorK simply checks against these numbers, so num_cmp($b) will expect 6 as a correct answer, and num_cmp($c) will expect 9 as a correct answer.
Because num_cmp invokes the WeBWorK mathematical libraries, when you pass a string to it, it evaluates it using its methods for evaluating formulas, so it will treat ^ as exponentiation. Thus num_cmp($d) and num_cmp($e) will both expect 9 as the correct answer. The difference between these and the previous is that for $b and $c all that is passed to the checker is the value, whereas in $d and $e the checker receives the whole expression.
To put it another way, num_cmp($b) is equivalent to num_cmp(6), whereas num_cmp($d) is equivalent to num_cmp("3^2").
We still haven't got to the reason that your expression is accepted, but not evaluated correctly, which has to do with raising negative numbers to even exponents.
Consider the following:
$p = -3;
$q = $p^2;
$r = $p**2;
$s = "$p^2";
$t = "$p**2";
Again, $q and $r are the result of perl calculations. $q ends up being some large number that you get when taking an XOR with a negative number. $r is the expected value of 9. $s and $t are the strings "-3^2" and "-3**2" respectively. When you pass $s or $t to num_cmp, it will evaluate either of them to -9.
In summary, if you put a calculation in quotes, then any variables will be substituted verbatim, and only calculated later, so things like this can occur. The implication is that if you put all bases in parentheses in your answer (e.g. ($c)^2, etc.), it should evaluate properly, which would be an alternative to the suggestions given by Alex and Andras.
As a further comment, if you are using MathObjects then you should follow Alex's suggestions and use the MathObjects answer checkers instead by replacing num_cmp($ans2) with $ans2->cmp().
One other benefit of MathObjects is that you can control the display of correct answers that is shown to students by using Compute on the string you would like displayed.
For example,
$a = 2;
$b = "ln($a)";
$c = Compute("ln($a)");
If you use num_cmp($b), then the correct answer column will show "0.693...", whereas if you use $c->cmp(), then the correct answer column will show "ln(2)", which is more helpful to a student.