6

Values like a +0. I are really annoying. Answers from

How to reduce expressions with complex coefficients in the form of a+0.*I? Is there a way to globally set when to treat a very small number as zero?

give me some clue, but I find $Post = Chop[#, 10^-16] &; doesn't work, for example :

Print[MatrixForm[FourierDCT[FourierDCT[{0, 0, 1, 0, 0}, 2], 3]]]

gives (0. -5.55112*10^-17 1. 1.38778*10^-17 1.38778*10^-17 ), which means the small digits still exist.

novice
  • 2,325
  • 1
  • 24
  • 30
  • What's wrong with Print[MatrixForm[FourierDCT[FourierDCT[{0, 0, 1, 0, 0}, 2], 3] // Chop]]? You can't use Chop outside the MatrixForm if that's the problem you've been having. – Jonathan Shock May 07 '13 at 05:55
  • 2
    But you know, it's probably a mistake to try to always hide small numbers --- someday you may need to know that they are not really zero. Just choose Chop whenever you want to display things. – bill s May 07 '13 at 05:57
  • Jonathan Shock: I don't know Chop fails outside the MatrixForm. But doesn't $Post = Chop[#, 10^-16] &; tells Mathematica to neglect digits smaller than 10^-16 automatically? – novice May 07 '13 at 06:12
  • @bills But isn't $Post (or $PrePrint) just the right thing to use whenever one wants to display things? The problem here is that it won't apply to Printed output (try it without the Print statement). – István Zachar May 07 '13 at 06:12
  • @bills, what if I need to compare a to an integer like If[a>3,..,..], whereas a is actually a + 0.I? Then error occurs. – novice May 07 '13 at 06:14
  • @novice, the $Post command will apply this to the output expression but given that the expression itself is generated using MatrixForm I don't expect it to work on the numbers inside it. Try applying Chop to your MatrixForm expression and see what it does. – Jonathan Shock May 07 '13 at 06:17
  • @Jonathan Shock Is there a way to confine all the numbers to real numbers in a program? Because I don't need imaginary number. – novice May 07 '13 at 07:53
  • 1
    The default for all numbers is Complex. But if you use only rationals (and don't do stuff like Sqrt[-rational] then everything will remain rational. But if you do operations that generate complex numbers (like Sqrt or roots of polynmials, there are lots!) then you need to deal with it explicitly. You can always apply Re to take only the real part or Chop to remove small imaginary values. – bill s May 07 '13 at 08:35
  • 1
    Keep in mind that an array that contains both pure reals and complexes can't be packed, so it'll take more memory and calculations will be slower. An array with all complexes (some of which have imaginary part 0.) can be packed without problems. – Szabolcs May 07 '13 at 20:37

1 Answers1

5
$PrePrint = Chop

will work fine for suppressing small approximate numbers in the display of your results. However, it won't have an effect on the the output generated by Print:

expr = FourierDCT[FourierDCT[{0, 0, 1, 0, 0}, 2], 3]

{0, 0, 1., 0, 0}

Print[expr]

{0., 0., 1., 2.64289*10^-17, 1.54951*10^-18}

That's because $PrePrint (and also $Post) are applied after the expression has evaluated, which means (counter-intuitively) that Print has already printed by the time that $PrePrint does anything. (MatrixForm has nothing to do with the problem.)

To get Print to go along with the program, you could inject a Chop into it using the Villegas-Gayley hack:

Unprotect[Print]; 
Module[{inside}, 
  Print[expr__] /; ! TrueQ[inside] := 
    Block[{inside = True}, Print @@ Chop@{expr}]
]
Protect[Print];

Now we have

Print[expr]

{0, 0, 1., 0, 0}

Note that this kind of thing may lead you into trouble, since the display of expr now doesn't match its internal representation. For example, if you want to find the positions of the zero elements, by looking at the displayed form, you might think that Position[expr, 0] would do the trick. But really you would need Position[expr, _?(Chop[#] == 0 &)] (or Position[Chop@expr, 0]).

Simon Rochester
  • 6,211
  • 1
  • 28
  • 40