## Replace very small numbers by zero in the output of a list

12

2

I have a long nested list, but many elements are numbers of order 10^-18 or less, e.g.

{{0.217548, -0.217548, -0.0373272, -9.83823*10^-18, -8.13807*10^-19}, \
{0.217548, 0.217548, 0.0373272, 7.54332*10^-18, 6.23849*10^-19}, \
{0.183095, 0.0504041, 0.00207916, -0.214279, -0.0218996}, \
{0.985472, -0.193791, -0.461242, 4.17611*10^-20, 1.22184*10^-20}, \
{0.985472, 0.193791, 0.461242, -1.18329*10^-30, -9.86076*10^-31},
{0.60405, 9.7862*10^-23, -9.11593*10^-24, -1.54354*10^-22, -1.91278*10^-23}, \
{0.80994, 0.556147, 0.623645, 0.558531, 0.625958}}


Then, to make the output more readable, I want to print in the output the numbers with absolute value smaller than 10^-18 as zeros.

What is the smartest and fastest way to do this?

How about N[results, precision] (http://reference.wolfram.com/mathematica/ref/N.html)?

– Tony Dong – 2013-03-19T15:59:46.893

2If dealing with reals, Chop your list. The second argument defines the threshold for zero. – Yves Klett – 2013-03-19T16:07:50.283

@YvesKlett Exactly what I needed. Thanks. – psmith – 2013-03-19T16:12:37.053

Why don´t you provide a sample list in your question? That would be instructive. BTW, not sure if this is not a duplicate or too localized (we´ll see). – Yves Klett – 2013-03-19T16:15:27.330

Perhaps you should also change the question title a bit, since you are not really after the precision but a simple chopping (at least my answer assumes that). – Yves Klett – 2013-03-19T16:40:00.647

12

This is rather basic ,but since it helped you, I´ll post the answer and leave it to the other users to judge.

The second argument to Chop (see Details section) defines the magnitude below which values will be replaced by 0.

l = {{0.217548, -0.217548, -0.0373272, -9.83823*10^-18, \
-8.13807*10^-19}, {0.217548, 0.217548, 0.0373272, 7.54332*10^-18,
6.23849*10^-19}, {0.183095, 0.0504041,
0.00207916, -0.214279, -0.0218996}, {0.985472, -0.193791, \
-0.461242, 4.17611*10^-20, 1.22184*10^-20}, {0.985472, 0.193791,
0.461242, -1.18329*10^-30, -9.86076*10^-31}, {0.60405,
9.7862*10^-23, -9.11593*10^-24, -1.54354*10^-22, \
-1.91278*10^-23}, {0.80994, 0.556147, 0.623645, 0.558531, 0.625958}};

Chop[l, 10^-18]


{{0.217548, -0.217548, -0.0373272, -9.83823*10^-18, 0},
{0.217548, 0.217548, 0.0373272, 7.54332*10^-18, 0},
{0.183095, 0.0504041, 0.00207916, -0.214279, -0.0218996},
{0.985472, -0.193791, -0.461242, 0, 0},
{0.985472, 0.193791, 0.461242, 0, 0},
{0.60405, 0, 0, 0, 0}, {0.80994, 0.556147, 0.623645, 0.558531, 0.625958}}

9

You can also use Threshold:

l = {{0.217548, -0.217548, -0.0373272, -9.83823*10^-18, -8.13807*10^-19},
{0.217548, 0.217548, 0.0373272, 7.54332*10^-18,  6.23849*10^-19},
{0.183095, 0.0504041,  0.00207916, -0.214279, -0.0218996},
{0.985472, -0.193791, -0.461242, 4.17611*10^-20, 1.22184*10^-20},
{0.985472, 0.193791,  0.461242, -1.18329*10^-30, -9.86076*10^-31},
{0.60405,  9.7862*10^-23, -9.11593*10^-24, -1.54354*10^-22, -1.91278*10^-23},
{0.80994, 0.556147, 0.623645, 0.558531, 0.625958}};

Threshold[l, 10^-18] (* or Threshold[l,{"Hard",10^18}] *)

(* {{0.217548, -0.217548, -0.0373272, -9.83823*10^-18, 0.},
{0.217548,  0.217548, 0.0373272, 7.54332*10^-18, 0.},
{0.183095, 0.0504041, 0.00207916, -0.214279, -0.0218996},
{0.985472, -0.193791, -0.461242,  0., 0.},
{0.985472, 0.193791, 0.461242, 0., 0.},
{0.60405, 0., 0.,  0., 0.},
{0.80994, 0.556147, 0.623645, 0.558531, 0.625958}} *)


FWIW, it seems to be faster than Chop for large lists:

 dt = RandomReal[1, {1000000}, WorkingPrecision -> 40];
dtchp = Chop[dt, 10^-18]; // AbsoluteTiming
(* {0.3110311,Null}*)
dtthrshld = Threshold[dt, 10^-18]; // AbsoluteTiming
(* {0.240023,Null} *)
dtchp == dtthrshld
(* True *)


4@YvesKlett probable explanation is that Chop replaces the values with exact zero, which involves unpacking the list if packed to start with. Threshold uses a machine zero and doesn't need to unpack. Since arbitrary precision values can't be stored in packed arrays anyway, Chop and Threshold are going to be similar in this case. – Oleksandr R. – 2014-01-01T22:51:26.783

My machine puts Chop slight in front of Threshold with altered precision (and using real 10.^-18 helps as well), while Threshold smokes Chop for standard precision - any explanations? – Yves Klett – 2013-03-19T17:45:10.573

@Yves, good observation (confirmed on Version 9 Windows Vista 64bit). Don't have any idea why, though. – kglr – 2013-03-19T18:19:14.310

4

The solutions above would be also my choice, but to give a more complete picture, here is an additional approach.

This generates the list with small valuse and those about a unity:

lst = Table[RandomReal[{-2, 2}]*10^RandomReal[{-10, 1}], {45}]


this solves the task replacing items smaller than 10^-5:

lst /. x_ /; Abs[x] <= 10^-5 -> 0


This is the result:

 {-0.00716429, -0.0364071, -0.000281284, 0, -0.000856377, 0, 0.164907, \
-0.0516522, -0.000840723, 0, 0.0467477, -12.1348, -0.636598, \
-0.0000171288, 0, 0, 0, 0.0910157, -0.0000228134, 0, 0, -0.396028, 0, \
0, 0, 0, -0.129861, -0.000599652, 0, 0, -0.00824202, 0, 0, 0.0181993, \
-0.0000162593, 0.00320663, -0.248421, 0, 0, 0, 0.0031162, 0.0363161, \
0.0216937, 0, 0}


May I ask a question? Is there any alternative to display two decimal places without AccountForm? I follow your advice and append "AccountForm" in front of the expression AccountingForm[lst /. x_ /; Abs[x] <= 10^-4 -> 0, 2] e.g {0.342416, 0.304959, 0, 0.352625} -> {0.34, 0.3, 0, 0.35} – madeinQuant – 2016-02-18T07:03:36.307

1@Nelson Mok I am not quite sure to have understood your aim. I have the impression that just for visualization you would like to have a shorted representation of the terms in the list, say, with two figures after comma, right? If yes, you may use the NumberForm function in such a way: lst = Table[RandomReal[{-2, 2}]*10^RandomReal[{-10, 1}], {45}]; lst1 = lst /. x_ /; Abs[x] <= 10^-5 -> 0; Map[NumberForm[#, {3, 2}] &, lst1] . Have fun! – Alexei Boulbitch – 2016-02-18T08:33:54.870