You'll get a lot of differing views on this but my take is that the code should be self-documenting i.e. it is written well enough that its purpose can be easily seen by reading it.
This is by no means always possible so if you have a chunk of complicated code your comments should be sufficient to explain how it works.
There is nothing worse then getting someone else's code (or your own after a few months) and finding a complicated section with a comment at the top that says,
for example, "this parses the data into the correct format".

I thoroughly comment my code but sometimes I fail to do so when the code is rushed out of me. Describing exactly what complex code is doing will save you time and pain when you have to exam it months from its origin date. Take the time now to save time later works best in my opinion.

First, there can never be too many comments on interfaces, that is, function declarations, class declarations, modules, or whatever else your language has as interfaces between the users and the library code. The only limiting factor in documenting interfaces should be the time you have and the efforts you are willing to put into writing it. And, of course, with limited time and effort, you have to prioritize by documenting more the functions that have more complicated behavior to specify (there's no point wasting too much time writing lots of documentation for a simpler getter or setter function). And, of course, this should be done using the document generation tags that are relevant to your language (like doxygen for C/C++, javadoc for Java, epydoc / sphinx for Python, so on..).

However, within the actual code, it's a whole different ball-game. In this case, it's a bit more of a matter of personal preferences, but there is also a pretty wide consensus that too many comments impede readability of the code. Always remember that programmers are much more used to reading code than reading english.

There are a number of ways to ensure that code is self-explaining and easily readable. Using good names for variables and functions goes a long way to make the logic self-evident (as a counter-example, in a code-base I work with now, they picked vague and senseless names like "Driver", "Action", "Task", "Invocation", "Instance", and "FrontEnd" for a set of related classes where none has a well-defined purpose, that's what you should never do).

Keeping the code well spaced out and idiomatic (conventional) makes it a lot easier to read.

Then, there are a number of coding practices (which vary a bit from language to language) to design cleaner and low-overhead abstractions and more self-contained classes that makes a lot of the code simpler and safer, without all the clutter. For example, well-designed code can typically avoid ugly things like try-catch(-finally) blocks (especially the finally blocks, which are an abomination and are basically modern-day goto's). Basically, code should look as clean as pseudo-code (for example, I've published pseudo-code for algorithms that I copy-pasted directly from my C++ actual code and only needing a simple literal translation of the syntax, nothing more).

Once you've followed those guidelines, there shouldn't be much need for comments within the actual code. I usually limit myself to a few one-line comments at the major steps. It's only when you have some tricky logic, like some non-obvious set of if-statements or termination conditions, that it can be helpful to add some notes explaining why it works out that way, so that you or some other reviewer of the code doesn't get puzzled by it, or worse, carelessly "fixes" it to some "simpler" logic without realizing he's actually breaking the code.

I agree with the above.
Time spent on variable, method/function, and class names is time well spent because it leads to code that needs no further explanation.
Personally I'm a fan of the quick one-liner at the top of each block of code stating what it dis going to achieve (eg // get item number from user and validate it... ) because that makes it easier to find the right part of the code.
The one place where the code itself needs comments is where it would be unreasonable to expect the reader to be familiar with the algorithm you are using. Eg I recently needed code to model two balls (different sizes/weights) bouncing off each other. The comment was longer than the code.

I have a 2d matrix with dimension (3, n) called A, I want to calculate the normalization and cross product of two arrays (b,z) (see the code please) for each column (for the first column, then the second one and so on).
the function that I created to find the ...

Write a C program that should create a 10 element array of random integers (0 to 9). The program should total all of the numbers in the odd positions of the array and compare them with the total of the numbers in the even positions of the array and indicate ...