A NURBS differs from a Bezier curve in two ways...
1) It's rational which means that it's one curve divided by another. (rational comes from "ratio", not anything to do with it's temperament!)
Being rational is not an issue though for being simple to evaluate. There are even such things as rational Bezier curves, where again, you just divide one Bezier curve by another to get the final result.
This allows you to make shapes with Bezier curves that you wouldn't be able to otherwise, for instance, rational Bezier curves can EXACTLY represent conic sections.
Here's an HTML5 demo where you can play with a rational Bezier curve:
Also, here is a shadertoy which uses a rational Bezier curve to calculate sin!
2) The second difference is the one that makes it more difficult to evaluate, at least for me. The second difference is that a NURBS, like a B-spline, can have any number of control points, but has a fixed degree. How this works is that any given point on the curve is only influenced by a specific number of control points.
You could have for example a quadratic curve with 8 control points, where each point on the curve was only defined by 3 of the control points at a time.
Where the influence of the control points begin and end is called the knot vector.
So basically, if you can evaluate a rational curve, and you can evaluate a b-spline, you will then know how to evaluate a NURBS.
Explaining how to evaluate a b-spline is too long for an answer I think, and there is lots of info on the web, and in text books, so i'll link to a couple things that might help you!
Read up on De Boor's algorithm, its the b-spline equivalent of De Casteljeau's algorithm:
Here is a shadertoy rendering a b-spline in a pixel shader:
Here is info on how to evaluate a b-spline:
Also, here is some code (GLSL) that shows how to evaluate an 8 control point cubic B-spline:
float N_i_1 (in float t, in float i)
// return 1 if i < t < i+1, else return 0
return step(i, t) * step(t,i+1.0);
float N_i_2 (in float t, in float i)
N_i_1(t, i) * (t - i) +
N_i_1(t, i + 1.0) * (i + 2.0 - t);
float N_i_3 (in float t, in float i)
N_i_2(t, i) * (t - i) / 2.0 +
N_i_2(t, i + 1.0) * (i + 3.0 - t) / 2.0;
float N_i_4 (in float t, in float i)
N_i_3(t, i) * (t - i) / 3.0 +
N_i_3(t, i + 1.0) * (i + 4.0 - t) / 3.0;
float SplineValue(in float t)
P0 * N_i_4(t, 0.0) +
P1 * N_i_4(t, 1.0) +
P2 * N_i_4(t, 2.0) +
P3 * N_i_4(t, 3.0) +
P4 * N_i_4(t, 4.0) +
P5 * N_i_4(t, 5.0) +
P6 * N_i_4(t, 6.0) +
P7 * N_i_4(t, 7.0);
I guess your question boils down to: Is there a way to do De Boor's algorithm as an equivalent equation, the same way Bernstein polynomials are an equation form of De Casteljeau's algorithm.
I'm not sure, but since there are "branches" (see N_i_1 in the glsl code), it seems like it'd be difficult. Maybe someone else will have a more direct answer to that part of it though.