# N not behaving in the way I expected it would [duplicate]

I'm trying to use the N function to find the percent error between a function and a rounded value of that function. The code looks something like this.

In[20]:= Tan[10°]

Out[20]= Tan[10°]

In[21]:= N[Tan[10°]]

Out[21]= 0.176327

In[22]:= N[%20] - N[%20, 4]

Out[22]= 0.

In[23]:= N[%22]

Out[23]= 0.


Basically, Mathematica is not recognizing these differences, and thinks they're 0 even when they're not. Does anyone have a workaround for this? I'll probably use IntegerPart if nobody has any thoughts.

## marked as duplicate by Mr.Wizard♦Mar 4 '17 at 17:05

• I don't get the same result. Your difference calculation returns 0.*10^-5 on my machine (Mathematica 10.3 on Win7-64), which seems reasonable to me. Alternatively, try the following: Tan[10 Degree] - Round[Tan[10 Degree], 0.0001]. – MarcoB Nov 12 '15 at 1:43
• I get your result, MarcoB, and it makes sense for smaller approximations. However, when one substitutes the accuracy value of 4 in line 22 with one of 1, you would expect a significant value, but you still get that 0.*10^-5 – mjkaufer Nov 12 '15 at 2:00
• Welcome to Mathematica.SE! I suggest the following: 1) As you receive help, try to give it too, by answering questions in your area of expertise. 2) Take the tour! 3) When you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. Also, please remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign! – Michael E2 Nov 12 '15 at 2:45
• Related: (10624) – Mr.Wizard Mar 4 '17 at 17:06

You have a faulty understanding of Mathematica's arbitrary precision arithmetic facility. N given a 2nd argument does not round or truncate a machine precision number (which essentially exist in their own numeric facility separate from the arbitrary precision facility) given as its 1st argument.

a = Tan[10 °];
Precision[N[N[a], 4]]


MachinePrecision

This explains the result you see as Out[22] and Out[23]. Now let's examine why N won't work for estimating errors.

b16 = N[a, 16]; b4 = N[a, 4]; Precision[b16 - b4]


0.

Because b4 has no significant digits in the part where it might be thought to differ from b16, there is no precision in the difference.

Here is how to estimate the relative error of rounding to four places:

a4 = Round[a, 1*^-4]; N[1 - a4/a]


0.000153015

### Update

A comment to this answer made by the OP persuades me to add this addendum to shed some light on what may be common misconceptions concerning Mathematica's arbitrary precision arithmetic.

First let us look at the internal forms of a, a evaluated with machine arithmetic, and a evaluated with arbitrary precision arithmetic with various setting for precision.

FullForm /@ Join[{a, N[a]}, Table[N[a, p], {p, Range[4, 20, 4]}]]

{
Tan[Times[10,Degree]],
0.17632698070846498,
0.176326980708464973471090386868618986124.,
0.176326980708464973471090386868618986128.,
0.1763269807084649734710903868686189861212.,
0.1763269807084649734710903868686189861216.,
0.176326980708464973471090386868618986121633062348098660214920.
}


It may come as a surprise that Mathematica retains many more digits than the precision specification called for; it retains the extra digits as guard digits to preserve accuracy during computation. It may be even more surprising that Mathematica retains the same large number of guard digits for 4-digit precision as for 16-digit precision, and that the lower precision number only differs in its terminating precision tag, but that is the case. However, that tag makes all the difference when it comes to the way numerical functions treat such numbers.

For example, let's look at Rationalize.

Consider rationalizing b16 in a smaller and smaller rational interval.

Rationalize[b16, #] & /@ (10^-Range[4, 16, 4])


{43/244, 1950/11059, 168214/953989, 15657047/88795526}

The rational approximation becomes more and more accurate, as it should.

But now consider, rationalizing b4 in the same environment.

Rationalize[b4, #] & /@ (10^-Range[4, 16, 4])


{70/397, 70/397, 70/397, 70/397}

This time the rational approximation doesn't improve, because b4, despite having the same internal digits as b16, is treated by Rationalize exactly like the low precision number it designated to be.

So don't take N for granted and treat it as if it were a simple numerical evaluator that truncates or round results. It is not that at all; it is a sophisticated tool that should be used with understanding and respect.

I strongly urge anybody new to Mathematica and who wants to do more than school-level numerics to take the time to familiarize themselves with its extensive and rather good Documentation Center articles on numerics, starting with this one.

• Got it - so basically, the second parameter on the N function just changes how the number is displayed, rather than the actual value of the number. – mjkaufer Nov 12 '15 at 18:16
• @mjkaufer. No, No, NO. N[a], b16, and b4 are entirely different numbers. The point I wanted (and obviously failed) to make is that N is a more complex numerical evaluator than it appears on the surface, and it is definitely not just an number display formatter. N is worth considerable study because to that. – m_goldberg Nov 12 '15 at 18:53
• In all honesty, I'm not getting this, even after your addendum. What does N do when given a second argument? Is it something akin to SetPrecision? – LLlAMnYP Nov 12 '15 at 22:43
• @LLlAMnYP. When given a 2nd argument, N tries to return a result of the specified arbitrary precision, rather than one of machine precision. This means it switches computation engines. I presume after doing so, N checks the values of $MinPrecision and $MaxPrecision, which could have values that force it act like SetPrecision, but that is not the default situation. – m_goldberg Nov 13 '15 at 2:18
• @m_goldberg Thanks for a great explanation of something I've never understood. One question: Why is the final digit of N[a] different from the rounded value of (say) b20? – rogerl Mar 4 '17 at 17:20

To obtain numerical accuracy you have to manually increase the precision of the obtained numerical value

SetPrecision[N[Tan[10 °]], 30] - Tan[10 °]
(* 1.929227666420*10^-18 *)