g | x | w | all
Bytes Lang Time Link
111C gcc241024T194211ZDaniel S
111Python160201T203627ZDigital
011MATL160131T174741ZLuis Men
083ES6160131T101459ZNeil
011Jelly160131T200522Zlirtosia

C (gcc), 111 bytes

s;r;c(p,n)float*p;{r=0;for(;--n;p+=2){s=p[3]>0?1:-1;r+=s*((p[1]>0?1:-1)-s&&(*p*p[3]-p[1]*p[2])*s>0);}return r;}

Try it online!

Input is expected to be a flattened array p of the coordinates with the first and last points being the same, along with the number of points n (counting the duplicate first and last points separately).

Explanation: Unlike the prior answers, this one is based on counting the number of intersections of the path with the positive x-axis, with orientation considered. The piece *p*p[3]-p[1]*p[2] is based on the fact that the line joining \$(a,b)\$ and \$(c,d)\$ hits the x-axis at \$\frac{ad-bc}{d-b}\$; however, in the case that \$b\$ and \$d\$ have opposite signs so that this intersection is actually on the line segment, then \$\frac{1}{d-b}\$ has the same sign as \$d\$.

(Note that in order to properly handle cases where one or more of the points are exactly on the positive x-axis, the code considers such points as equivalent to being very slightly below the x-axis.)

Python, 111

Longest answer so far. My motivations are 1) learn python and 2) possibly port this to pyth.

from cmath import *
q=input()
print reduce(lambda x,y:x+y,map(lambda (x,y):phase(x/y)/pi/2,zip(q[1:]+q[:1],q)))

Input is given as a list of complex numbers.

Ideone.

I think the approach is similar to the ES6 answer.

When 2 complex numbers are multiplied, the argument or phase of the product is the sum of the argument or phase of the two numbers. Thus when a complex number is divided by another, then the phase of the quotient is the difference between the phases of the numerator and denominator. Thus we can calculate the angle traversed through for each point and the next point. Sum these angles and divide by 2π gives the required winding number.

MATL, 11 bytes

X/Z/0)2/YP/

Input is a sequence of complex numbers including the end point.

Try it online!

Explanation

Most of the work is done by the Z/ function (unwrap), which unwraps angles in radians by changing absolute jumps greater than or equal to pi to their 2*pi complement.

X/       % compute angle of each complex number
Z/       % unwrap angles
0)       % pick last value. Total change of angle will be a multiple of 2*pi because 
         % the path is closed. Total change of angle coincides with last unwrapped
         % angle because the first angle is always 0
2/       % divide by 2
YP/      % divide by pi

ES6, 83 bytes

a=>a.map(([x,y])=>r+=Math.atan2(y*b-x*c,y*c+x*b,b=x,c=y),b=c=r=0)&&r/Math.PI/2

Takes as input an array of pairs of points which are interpreted as complex numbers. Rather than converting each point into an angle, the points are divided by the previous point, which Math.atan2 then converts into an angle between -π and π, thus automatically determining which way the path is winding. The sum of the angles is then 2π times the winding number.

Since Math.atan2 doesn't care about the scale of its arguments I don't actually perform the full division z / w = (z * w*) / (w * w*) instead I just multiply each point by the complex conjugate of the previous point.

Edit: Saved 4 bytes thanks to @edc65.

Jelly, 11 bytes

æAI÷ØPæ%1SH

This takes input as a list of y-coordinates and a list of x-coordinates.

Try it here.