My rule is this: if there is something that needs to be said and the code can not be made to express it, then you may write a comment. Otherwise, if the code can express the idea, then you must express the idea in the code or its tests.
If you follow this rule, then your code should only need comments when it is dealing with some inobvious problem in the hardware or operating system, or when the most obvious algorithm is not the best choice. These are "this is weird because" comments, and really are just a coping mechanism.Most of the time comments in the code are really just apologies for not writing it in a more obvious way, and such comments should be obviated and then deleted.
Even the good comments often become lies over time, so information in non-executable, non-testable places like comments are to be eyed with suspicion. Again, the answer is to first obviate the comment, then delete it.
My ideal ratio is zero. However, the world is less than ideal, so I accept comments when there is no other way to communicate an important idea.