1) All programmers should have a basic grounding in math. I have seen way to many programmers who do not know de Morgan's law (!(a && b) )== (!a || !b) and that is not even remotely high level math. I have also seen too many people fail to realize that the converse of a true statement is not necessarily true. One needs a basic understanding of math in order to program well.
2) All programmers should have a basic grounding in theoretical Computer Science. I have had coworkers refuse to implement more efficient algorithms because they did not understand the concept of a DFA and did not care to listen to my explanation of it. Also one ought to understand why certain things simply cannot be determined by a computer program and what class of things this usually is.
3) Probably has a lot to do with the inclinations of the person.
Also, before anyone takes me out of context here I would like to point out that I am only calling for a "basic grounding" in the above. This does not necessitate formal education (although that is the most common method). A person could teach these things to herself; however, it is important that one actually learn them rather then delude oneself into thinking that they are known.
Computer science is merely the post-Turing decline of formal systems theory.