10
$\begingroup$

Why is it so? When I ask for

N[1.00001, 10]

I get quite reasonably

1.00001

But when I ask for

N[1.000001, 10]

I am getting unreasonable

1.

I thought I knew what N is about. But I must be making some trivial error. What is it?


Added May 23: Thanks for all your help.

$\endgroup$
15
$\begingroup$

This has nothing to do with N. You are observing the fact that by default Mathematica truncates machine precision numbers to 6 digits for displaying them. Enter 1.000001 without N and evaluate it: you'll see the same output (i.e. "1."). You can adjust this in Preferences, Appearance, Numbers, Formatting. The numbers are still stored to full precision, but not all digits are displayed.


A note about N: it does not affect machine precision numbers. It does affect other inexact numbers, but it won't increase their precision. It can only decrease it. To explicitly change precision, use SetPrecision.

x = 0.3;

Precision[x]
(* MachinePrecision *)

Precision[N[x]]
(* MachinePrecision *)

x = N[1/3, 10]
(* 0.3333333333 *)

Precision[x]
(* 10. *)

Precision[N[x, 5]]
(* 5. *)

Precision[N[x, 15]]
(* 10. *)
$\endgroup$
  • $\begingroup$ You say Mathematica truncates machine precision numbers to 6 digits for displaying them. But N[Pi,10] will give me 10 digits, while N[1.000001,10] gives me only 1 digit. Why? $\endgroup$ – arkajad May 22 '16 at 21:09
  • 3
    $\begingroup$ @arkajad, N[Pi,10] is not a machine precision number, therefore the rules for displaying machine precision numbers do not apply. $\endgroup$ – Simon Woods May 22 '16 at 21:23
  • $\begingroup$ Should not N[x,10] override the default displaying only 6 digits? $\endgroup$ – arkajad May 23 '16 at 7:54
  • $\begingroup$ @arkajad : The output of N[x,10] is either a machine precision number or is something else. Once it is evaluated, there is only the result, not some "extra piece" that can "override" something. If the result is a machine precision number, then it is displayed like a machine precision number. If it is not, then it is displayed in the manner of whatever the returned thing is displayed. $\endgroup$ – Eric Towers May 23 '16 at 18:12
  • $\begingroup$ @arkajad If x is a machine real, N[x, 10] won't change that (as Szabolcs said; probably in the docs, too). You can override with SetPrecision[x, 10] but you still might get something slightly different since the binary value of x might not convert back to the decimal form you input $\endgroup$ – Michael E2 May 24 '16 at 7:07
11
$\begingroup$

Hint: try

In[1]:= FullForm[N[1.000001, 10]]

which returns

Out[1]//FullForm= 1.000001`

That tells you the 'rounding' is happening on the front end only, but that the full precision you asked for is still there.

Roughly speaking, objects have an internal representation, and the front end 'interprets' this representation to produce the display in a notebook. Any object in a Mathematica calculation "really is" its internal representation, which can be accessed using FullForm or InputForm; for an interesting example try producing e.g. Plot[Sin[x], {x, 0, 10}], and then copy-pasting the resulting plot into the inside of InputForm and running that. The resulting code,

Graphics[{{}, {}, {RGBColor[0.368417, 0.506779, 0.709798], 
   AbsoluteThickness[1.6], Opacity[1.], Line[{{2.0408163265306121*^-7, 
    2.0408163265305978*^-7}, {0.0030671790804136087, 
    0.0030671742712899356}, {0.006134154079194564, 0.006134115610099161}, 
    {0.012268104076756476, 0.012267796341088115}, {0.0245360040718803, 
    0.024533542303539827}, {0.049071804062127945, 0.04905211193942774}, 
...

is what the plot "really is", as far as the back end (a.k.a. the kernel) is concerned. When you run the Plot command, the back end hands the front end the expression above, and the front end has some special rules about e.g. how expressions that start with Graphics get displayed.

Similarly, when you ask for N[1.000001, 10], the back end dutifully returns 1.000001`, and this is the "real" form of the object (which amongst other things will be used in further calculations with that quantity, such as setting x = N[1.000001, 10] and then asking for x-1). However, as is the case with Graphics objects, the front end has some special rules about how decimals get displayed (i.e. machine-precision numbers are not displayed past the sixth significant figure, with that threshold being editable as explained in Szabolcs' answer), but the full precision (obtainable via InputForm or FullForm) is still there.


Addendum, in reply to OP's comment,

I would like to understand why N[1000001/1000000,10] gives me 1.000001000, while N[1.000001,10] gives me 1. Why Mathematica likes and respects more the rational form of a number than exactly the same number but written in a shorter, decimal form?

The mistake is in saying "gives me"; you need to think of it as "gets displayed as" by the Front End (which is very separate from the kernel that actually does the computations). Run both alternatives through FullForm and you'll get a window into why they're being treated differently.

In[1]:= FullForm[N[1000001/1000000, 10]]
In[2]:= FullForm[N[1.000001, 10]]

Out[1]//FullForm= 1.000001`10.
Out[2]//FullForm= 1.000001`

What does this mean, exactly?

  • When you input 1.000001, the kernel recognizes it as a machine-precision number and this is denoted by a crucial distinction, which is appending a backtick (`) at the end, to transform it into 1.000001`. This indicates that the number is known to machine precision and should be handled accordingly.
  • When you input 1000001/1000000, this gets treated as a Rational expression with infinite precision. When you then ask Mathematica to turn this into a numerical expression to 10 digits of precision using N[_, 10], it gets calculated to be 1.000001, but the crucial part is that it gets tagged as a finite-precision number, by appending the precision (10) after a backtick, to give 1.000001`10.

  • When you run N[1000001/1000000, 10], the kernel calculates it to be 1.000001`10, and then hands it to the Front End so it will get displayed. The Front End sees a finite-precision number, and it applies the display rules for finite-precision numbers, which specify that they should get displayed with as many significant figures as their precision. That's why the Front End displays it as 1.000001000.

  • In contrast, when calculating N[1.000001, 10], the kernel hands over 1.000001` for the Front End to display, and now the display rules are the rules for machine precision numbers, which specify that (by default) only six significant figures should be displayed.

The difference between the two, then, is in whether they have an explicit precision indicated. If you want 1.000001 to be displayed to ten decimals, then you need to indicate that exactly ten decimals are relevant, and the way to do this is not via N but by giving an explicit precision. The simplest way is to say

In[3]:= 1.000001`10
In[4]:= FullForm[1.000001`10]

Out[3]= 1.000001000
Out[4]//FullForm= 1.000001`10.

by simply giving an explicit precision after a backtick. Note that in this case the Front End displays all ten significant figures you asked for, but the kernel still doesn't care about anything after that last 1: as far as the kernel is concerned, the number is still 1.000001 (and not 1.000001000), now with a finite precision tag.

Alternatively, you can force a specific precision by using SetPrecision, as

In[5]:= SetPrecision[1.000001, 10]

Out[5]= 1.000001000

Note, however, that this does something quite interesting on the back end of that number:

In[6]:= FullForm[SetPrecision[1.000001, 10]]

Out[6]//FullForm= 1.00000099999999991773336205369560047984`10.

What's happened here? The FullForm of the number has now changed to something with a bigger tail, which is still consistent with the desired 1.000001000 to the specified ten digits of precision. Here, however, you're using SetPrecision to pad out a number to the right with zeroes, and here the behaviour is described in the SetPrecision documentation:

When SetPrecision is used to increase the precision of a number, the number is padded with zeros. The zeros are taken to be in base 2. In base 10, the additional digits are usually not zeros.

If you're going to pad 1.000001 out to 1.000001000, then why should base 10 be best way to do it? The processor sees numbers in base 2, so that's what this does. Again, it returns a number consistent with your specifications, so you cannot complain.

To emphasize the effect of a specified precision on how numbers get displayed, run the following examples by themselves and through FullForm:

  • 123123123123
  • 123123123123.
  • 123123123123.`
  • 123123123123.`8
  • 123123123123.`12
  • 1.000000999`10
  • 1.0000009999`10
  • 1.1234567898964531234856748910456`
  • 1.1234567898964531234856748910456`35

And finally, to forestall your next question:

Shouldn't N[1.000001, 10] return a number with 10 digits of precision specified, as 1.000001000`10?

The answer is a strong no: your input, 1.000001, is a machine-precision number, which means by default it is understood to have ≃16 digits of precision. Paring it down to 1.000001`10 then loses six digits of precision in the internal calculations for the superficial, purely visual, benefit of seeing the number print out as 1.000001000. Moreover, doing arithmetic with numbers with arbitrary precision is much more expensive than doing arithmetic with machine-precision floats, which gets handled automatically by the bare-metal processor and is therefore much faster. We want N to maintain machine-precision numbers as such in the name of efficiency.

Moreover, this is explicitly stated in the documentation for N:

With machine-precision input, the results are always machine precision:

In[1]:= N[Gamma[3.3],50]
Out[1]= 2.68344

(and, moreover, asking for FullForm[N[Gamma[3.3], 50]] returns an explicit machine-precision number, 2.6834373819557684 ``, which is only pared down to six significant figures by the Front End, as standard). This behaviour is codified in the documentation so it is the expected and desired behaviour for this function.

If it's the display you care about, then this is less to do with the language itself (i.e. the specs of how N should behave at the kernel level) and more to do with how the Front End is configured to display stuff. If you want to see 1.000001 to ten digits of accuracy, you've got plenty of options,

  • entering as 1.000001`10,
  • asking for the FullForm of 1.000001, or overall
  • changing the PrintPrecision option for the notebook,

none of which mess with how fast the output of N gets treated by subsequent computations.

$\endgroup$
  • $\begingroup$ Nice explanation. $\endgroup$ – Anton Antonov May 23 '16 at 4:23
  • $\begingroup$ Thank you for that. But I would like to understand why N[1000001/1000000,10] gives me 1.000001000, while N[1.000001,10] gives me 1. Why Mathematica likes and respects more the rational form of a number than exactly the same number but written in a shorter, decimal form? Must I write my numbers in a rational form in order for Mathematica not to hide from me their values? Must it be so? Or it is a bug? $\endgroup$ – arkajad May 23 '16 at 7:47
  • $\begingroup$ @ark, in the view of Mathematica, numbers with a decimal point are inexact numbers, and thus subject to the vagaries of (machine or arbitrary precision) floating point arithmetic. $\endgroup$ – J. M. is away May 23 '16 at 8:50
  • $\begingroup$ @arkajad See edit. This is very much not a bug. $\endgroup$ – Emilio Pisanty May 23 '16 at 11:06
3
$\begingroup$

If you want to tweak the number of digits displayed in your notebook, run this:

SetOptions[EvaluationNotebook[], PrintPrecision -> 10]

As noted by Szabolcs, the default setting of PrintPrecision is 6, which is why you're only seeing that many digits in the output, even tho all the digits are still there.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.