[?] Change the default number of digits to display in the output?

Here is some disturbing behavior that caused me a lot of trouble and was difficult to track down.

In[1]:= 50.01 + 50.03
Out[1]= 100.04

In[2]:= 500.01 + 500.03
Out[2]= 1000.04

In[3]:= 5000.01 + 5000.03
Out[3]= 10000.

Really? Definitely don’t use Mathematica for your accounting tasks. And it’s not a case of the lost digits actually being there but hidden when printing. Let’s try looking at 1000 digits just to be safe.

In[4]:= N[5000.01 + 5000.03, 1000]
Out[4]= 10000.

So we have to change the input precision, which is a problem I discovered long ago but have learned to live with to some extent. Although, sometimes it’s easier to just use the Windows Calculator. I wish there was a way to make Mathematica extend the precision of all numbers automatically if you wanted to.

But how much precision do we need to get the right answer? You might think, ok, in the last line the inputs have 6 significant digits and the answer has 7. So we should just have to add one extra 0 on the inputs to give them 7 digits.

In[5]:= 5000.010 + 5000.030
Out[5]= 10000.

But no. Let’s try adding a lot more.

In[6]:= 5000.01000000000000 + 5000.0300000000000
Out[6]= 10000.

Still not enough. We have to add a full 12 zeros on the end just to get the correct answer to 2 decimal places!

In[7]:= 5000.01000000000000 + 5000.03000000000000
Out[7]= 10000.0400000000000

I never liked the way Mathematica handled precision, and this makes me like it even less.

2 Likes

I think maybe this is not the perfect solution, because it is visual and also has limitations… but it might slightly improve your visualization if using AccountingForm []

AccountingForm[5000.01 + 5000.03, 7]
AccountingForm[5000.00000001 + 5000.00000003, 13]
AccountingForm[5000.00000000001 + 5000.00000000003, 16]

…I think maybe there’s still another better way…

You can try

5000.01`7 + 5000.03`7

 (* 10000.04   . *)
1 Like

Yes! This method is perfect! Works for many many decimal places! Thanks a lot, Marvin, I learned something new!

5000.0000000000000000000000000000001`36 + 5000.0000000000000000000000000000003`36

( * 10000.0000000000000000000000000000004 * )

I was aware of this method and should have mentioned it. In fact, it’s the way I worked around the problem in my notebook. But adding `x on the end of every number is just as tedious as adding 0’s, especially when you have a long list of numbers possibly copied from somewhere else.

Another issue with that is why doesn’t 5000.01`7 behave the same as 5000.010 or even 5000.0100000? What does the 7 even mean?

If you insist on copying and pasting data that is used elsewhere, try

 SetPrecision[5000.01 + 5000.03, 7]

(* 10000.04.*)

.

.. I’ve been thinking about a way of not having to manually put the precision number in SetPrecision… I found this way if you turn the numbers into string to then use the command. Is there any other way?

a = "5000.01700000";
b = "5000.00000000";
SetPrecision[(a // ToExpression) + (b // ToExpression), 
 StringLength[a]]

a2 = "50000.01700000";
b2 = "50000.00000010";
SetPrecision[(a2 // ToExpression) + (b2 // ToExpression), 
 StringLength[a2]]

a3 = "500000.017000000";
b3 = "500000.000000100";
SetPrecision[(a3 // ToExpression) + (b3 // ToExpression), 
 StringLength[a3]]

Thanks

1 Like

I like the SetPrecision idea, which I hadn’t thought of. Although, it can still be tedious to wrap every expression with SetPrecision. And as the last post suggests, it’s not always clear just how many digits you need. The problem as I stated it seems straightforward and easy to put a number on, but that was distilled from a more complicated series of calculations that took me a while to figure out what was going on. I guess you could just SetPrecision of every expression in a notebook to 10 or 100 or something just to be safe and make sure the numbers were being handled in the way you intended, but that seems rather crude.

I guess what I’m hinting at here is there is inconsistent behavior here at best and a bug at worst. I mean understand about computer numerical calculations and how this problem might arise, but Mathematica is supposed to give you consistent result regardless of the underlying hardware. Precision[5000.01] is MachinePrecision and $MachinePrecision is 15.9546. So why do you have to set the precision of 5000.01 to 7 to get the calculation to work when it is already supposed to have a precision of 16? And again, why does 5000.010 not behave the same as 5000.01`7?

This discussion is somewhat hard to understand. I anyone really thinking that there is a miscalculation?

3 Likes

I never implied a miscalculation, I’m saying misbehavior. 5000.01 + 5000.03 = 10000. is a problem all by itself. Mathematica might know the answer, but that doesn’t do the user any good when it gives an answer like that. Sure you can do tricks and apply function to get it spit out the right answer, but 5000.01 + 5000.03 = 10000. is just wrong. It’s wrong to 16 digits, which it supposedly is, and it’s wrong to 7 digits. And if you don’t like that 5000.010 + 5000.030 = 10000. is even more wrong.

I did not realize that all digits were still there internally. But that just points out another ‘flaw’. N[5000.01 + 5000.03, 1000] = 1000. So “1000.” is the correct answer to 1000 digits, even when it knows internally that the .04 is there?

So “1000.” is the correct answer to 1000 digits, even when it knows internally that the .04 is there?

No, one sees here just the same displaying behavior:

N[5000.01 + 5000.03, 1000] // FullForm
(*  Out:   10000.04`   *)
1 Like

Doug,

This is a function of your preferences. Go to preferences and change the default number of digits to display in the output from 6 to 10, or something else. Now it will show 10 digits of precision (while keeping any extra digits hidden). This rounding behavior is only for display and was done to make big expressions with lots of numbers manageable but if you change your preference, you can have what you want.

Alternatively, you can do this change for only one notebook and leave your global settings alone by going to the options inspector and changing PrintPrecision option for that notebook or executing this one time for a particular notebook:

SetOptions[SelectedNotebook[], PrintPrecision -> 10]

Regards,

Neil

5 Likes

What does “7” even mean

You can specify the precision of a number with the prime character. For example if I type 10. I get 10 to machine precision (normally about 16 digits) but if I type 10.`20 I get a floating point number with 20 digits of precision. You really need to read this tutorial.

Wow, good answer, Thanks.

That solves the problem, but I still feel like there are inconsistencies. Like why does 5000.01`7 + 5000.03`7 = 10000.04 with display digits set to 6, but N[5000.01 + 5000.03, 1000] = 1000. using the same settings?

If you explicitly set the precision, it overrides the default display option. This way you can distinguish terms with specific precision. It is rare that you would specify precision less than machine precision. I certainly would not do that for the display reason that you posted. (One example might be if you want to explore the affects of limited precision on a calculation). Usually you specify the precision to force MMA to use extended precision for a calculation that needs it.

Regards

1 Like

There are severa interrelatedl misconceptions about what value is being returned, whether or how to obtain a different value, what is printed visually vs what value is stored, and the like. This has, by and large, been noted in responses by Henrik Schachner, Neil Singer, and perhaps others. I want to spell out a few things.

(1) The inputs are machine precision numbers. A construct like N[value,100] will not change them because N will not raise precision, and machine precision is considered to be the lowest possible precision in the Wolfram Language.

(2) As noted by others, default precision shown is 6 digits. The comment about not using Mathematica for accounting was perhaps intended as an offhand remark, but regardless it should be noted that there is AccountingForm, for visual purposes (by which I mean it only does formatting, it does not alter values). I will cut-paste the example in question directly because it may give a better indication of what I mean.

In[11]:= val = 5000.01 + 5000.03

Out[11]= 10000.

In[12]:= AccountingForm[val, {Infinity, 2}]

Out[12]//AccountingForm= \!\(
TagBox[
InterpretationBox["\<\"10000.04\"\>",
10000.04,
AutoDelete->True],
AccountingForm[#, {
DirectedInfinity[1], 2}]& ]\)

Notice that the InterpretationBox gives the formatting of the value, to two [places to the right of the decimal point.

(3) SetPrecision can be used to raise precision. One should understand, however, that it might change the value in an unexpected manner. It works by taking the binary representation and padding with binary zeros. Since not all terminating decimal values have exact terminating binary counterparts, the value thus obtained may be different from the input. This can be useful (and I do use SetPrecision in certain circumstances to raise precision), but, for the reason above, it comes with a caveat.

(4) Default display precision for machine reals is 6 digits. It has been this way quite possibly since version 1.0. An alternative would be to show 16 or 17 digits. This could have been done but, on balance, I think the default is nicer. This is of course a subjective judgement. One can always get a better indication of the actual value using InputForm.

In[13]:= InputForm[val]

Out[13]//InputForm=
10000.04

The definitive value is the binary bit pattern, and that can be deduced from RealDigits:

In[14]:= RealDigits[val, 2]

Out[14]= {{1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
   1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 
  0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0}, 14}

(5) Entering values with increasingly many padded zeros at the right of the decimal point shows a change of behavior at the point where the inputs are no longer of a size that can be machine numbers. These are thus bignums, and subject to the display formatting used for such. It does not restrict to a default of 6 digits but rather shows all significant digits (in the sense of “significance arithmetic”).

(6) I hope it has become clear from prior responses that the subject heading is in error. There is no “precision error” in the computation claimed to be problematic. The default formatting might not be what was wanted, but by definition it is not possible to have a default that meets all possible needs. My guess is either AccountingForm or InputForm would be what was wanted here.

I hope the above provides some indication of the display-vs-actual-value, formatting possibilities, and reasons for the various outputs that were seen and in some cases called into question.

3 Likes

I thought that might be the case, but it seems wrong that setting the precision should override the digit display while the N function does not. If anything, it should be the reverse. Setting precision should only affect the internal representation of the number, not the display, whereas the N function is just about synonymous with “display more digits”. Seems like the problem now is the N function.

Thank you for your reply Daniel. I submitted my last response at about the same time and I was obviously referring to the post before yours.

I still do not feel 100% satisfied. I was aware of most of what you said, and I do vaguely remember something about 6 digits from when I was learning Mathematica years ago when I started with version 1.2, which is probably why I said “I never liked the way Mathematica handled precision”. But my comment about accounting was facetious.

I will agree that the title “Precision Error” is wrong. But I might defend the title “Precision Display Error”. Because I think that is what it is. Machine precision on most machines, I believe, is 16 decimal digits. The numbers I am talking about are well below that. I see no reason why decreasing the precision with SetPrecision should override the display precision. You’re making the number less precise, but then you display more digits than you do for the more precise original? If you set the precision to greater than machine precision then ok, it can display more digits. There’s no reason SetPrecision shouldn’t behave exactly the same way as padding with 0’s, as far as the number display.

And as I just mentioned, the N function is used specifically to display more digits. I understand that does not increase precision, but as even you demonstrated, there is already enough precision to store the full answer. So why do you have to use InputForm to see the whole number when the N function was seemingly made for that very purpose?

I did mention that the default display of six digits is a matter of subjective preference. It predates my arrival at the company by a bit, and at this point I am quite accustomed to it. But I am aware that it did not have to be that way, and there are arguments to be made for doing differently. As people may realize, we are of late extending some of this, what with new formatting forms e.g. DecimalForm and PercentForm, and with different notions of numerical computation as are under the hood in Around. And in a very recent live-broadcast development meeting, I believe the topic of how to more easily change the default displayed digits came up.

I want to go a bit further into a couple of areas. I’ll start by noting that machine precision in some sense has two meanings. One is the approximately 16 digits that a machine value has. For this there is $MachinePrecision in the Wolfram Language. In contrast, to denote computations that should take place using machine numbers, there is MachinePrecision (no dollar sign, that is). Numerically it evaluates to $MachinePrecision:

In[28]:= $MachinePrecision

Out[28]= 15.9546

In[29]:= N[MachinePrecision]

Out[29]= 15.9546

Yet is has a very different meaning in terms of how lower precision “infects” higher-- for that purpose it can be regarded as -infinity, in that bignums of any precision, even lower than $MachinePrecision, will be coerced to machine numbers when a computation is done using MachinePrecision. This relates to the present discussion as follows. SetPrecision[machinevalue,10] does not exactly lower the precision. Yes, it is lower than $MachinePrecision, but as it is now a bignum of precision 10 digits, it is regarded as higher than MachinePrecision. (Maybe more to the point, it is a bignum regardless of having precision lower than $MachinePrecision.) As a bignum it is subject to a different default behavior for display of digits.

The other point I will raise is that N is by no means a function for displaying digits. It is a function for obtaining a certain precision from either an exact value, or a value that is numeric but has higher precision than the number of digits in the second argument of N. How many digits get displayed by default then depends on whether the result is a bignum (of any precision) or a machine number; this is quite independent of the fact that the number was produced using N.

1 Like

Thank you for clearing that up. I’m glad my comments got through to someone who seems to have some influence on the direction of Mathematica so that maybe these issues can be considered in future improvements.

As I suggested, I’ve been using Mathematica for many years and it’s one of my core software tools. The things I’ve been able to do over the years would be unthinkable without it. I suppose I started off this thread being a bit critical, but I hope I’m ending it with some ideas for improvement.