Did you realise that you're adding numRect.top but subtracting numRect.left ?
Also, with circles it makes more sense to use the radius for the each origin member.
Note that a circle's local boundary is another case where left and top is not guaranteed to be zero. The width will take into account the outline so you'll need left and top of the local boundary too.
Try it without circle outlines to confirm that that is what is happening.