1
$\begingroup$

Is there a way to avoid the digits being changed?

In[117]:= v=124.58061;
v1=v-0.00024;
v2=v+0.00024;
In[120]:= FullForm[v]
FullForm[v1]
FullForm[v2]
Out[120]//FullForm= 124.58061`
Out[121]//FullForm= 124.58036999999999`
Out[122]//FullForm= 124.58085`
In[123]:= FullForm[Interval[{v1,v2}]]
Out[123]//FullForm= Interval[List[124.58036999999997`,124.58085000000001`]]

I just want 124.58037 and 124.58085 in these outputs. For some other values of v, the Out[122] would also get a small bit change.

How could I avoid the changes? Eventually I want to save these numbers (which is part of a larger structured expression) into files, what's the right way to do it without causing additional changes to the numbers?

$\endgroup$
  • $\begingroup$ 124.58036999999999 is exactly the same as 124.58037 - there is no change in the number. Evaluate SameQ[124.58036999999999, 124.58037] to see. If you are trying to write this number to a file and want it written in a certain way, then the question should clarify that. $\endgroup$ – Jason B. Dec 19 '18 at 2:07
  • $\begingroup$ Do you realize that the actual numbers are stored as binary64 reals? The change, if you want to call it that, occurs when M displays the numbers as the closest 6-digit approximation. What you see in the Front End is not the actual number. $\endgroup$ – Michael E2 Dec 19 '18 at 2:09
  • $\begingroup$ If it is SameQ, why not using the more intuitive form for both display and writing? $\endgroup$ – qazwsx Dec 19 '18 at 2:39
  • $\begingroup$ @qazwsx Because Mathematica is not consistent with how it displays numbers to the right of the decimal point. There are plans to make it more consistent in version 12. $\endgroup$ – Robert Jacobson Dec 19 '18 at 3:13
1
$\begingroup$

The Problem

There are two distinct issues at work:

  1. Why is the result of the simple arithmetic operation different from what you'd expect?
  2. How can we change the display (as opposed to the value) of a decimal number?

How "Real" numbers are represented internally

The answer to the first question is simple: Some numbers cannot be exactly represented in binary (base 2) with a finite number of digits, just as $\frac{1}{3} = 0.\overline{3}$ cannot be expressed in decimal (base 10) with a finite number of digits. Mathematica represents Real numbers internally as a single binary number called a floating point number, or float for short. On most systems, a 64-bit float only holds 53 binary digits for the mantissa (think scientific notation). You can see this for your numbers using RealDigits:

RealDigits[124.58061, 2, 54]
{{1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 
0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 
1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, Indeterminate}, 7}

That last Indeterminate is telling us there are no more known digits, and the 7 says how many digits are to the right of the decimal point (binary point?), a number Mathematica calls Accuracy. The bottom line is, converting from a finite number of decimal digits (what you entered) to a finite number of binary digits (internal representation) and then back again (for display) is not guaranteed to preserve the original input. This is fundamentally unavoidable when using floats.

How "Real" numbers are displayed

But with 53 binary digits at our disposal, you have ~14 decimal digits to the right of the decimal point to work with, which is more than enough for your desired 5 sig figs. Now your problem is how Mathematica is choosing to display the numbers to you. Mathematica is not consistent here. None of your three numbers has a terminating binary representation, but that's not apparent from the output of FullForm.

The Solution

Change the display

Since you have plenty of digits of precision to work with, it seems to me you want to change the display of decimal numbers. You can do this with DecimalForm. Here is the wrong way to use DecimalForm:

In[1]:= v = DecimalForm[124.58061, 9]
In[2]:= v1=v-0.00024
Out[1]//DecimalForm = 124.58061
Out[2]= -0.00024+124.58061

The number -0.00024 is displayed to 2 sig figs, just as it was entered, while v continues to be displayed with 9 sig figs. Here's the right way:

In[3]:= DecimalForm[v=124.58061 , 9]
        DecimalForm[v1=v-0.00024, 9]
Out[3]//DecimalForm= 124.58061
Out[4]//DecimalForm= 124.58037

Notice the placement of the = (assignment) operator. Keep in mind this only changes the display of the numbers, not the internal representation.

Change the internal representation

Alternatively, you can avoid using Mathematica Real numbers altogether. The best way is to use rationals instead as Bill suggests in his answer.

In[5]:= v=Rationalize[124.58061,0]
        v1=v-Rationalize[0.00024,0]
        v2=v+Rationalize[0.00024,0]
Out[5]= 12458061/100000
Out[6]= 12458037/100000
Out[7]= 2491617/20000

In each case, Mathematica has just reduced the fraction $\displaystyle \frac{x\cdot 10^5}{10^5}$. The N function will then give you as many decimal digits of precision as you'd like:

In[8]:= N[v2, 20]
Out[8]= 124.58085000000000000
$\endgroup$
2
$\begingroup$

Try this

v=Rationalize[124.58061,0];
v1=v-Rationalize[0.00024,0];
v2=v+Rationalize[0.00024,0];
FullForm[v+0.]
FullForm[v1+0.]
FullForm[v2+0.]

which shows me 124.58061, 124.58037 and 124.58085.

But expecting floating point binary math to provide exact decimal results may be an ongoing source of frustration and problems.

$\endgroup$

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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