Chapter 1. Numerics

Jenny I’ve got your number I need to make you mine Jenny don’t change your number Eight six seven five three oh nine Eight six seven five three oh nine Eight six seven five three oh nine Eight six seven five three oh nine

Tommy Tutone, “867-5309/Jenny”

1.0 Introduction

Numerical Types

Mathematics is a huge, almost all-encompassing subject, and the average layperson often fails to appreciate the types of exotic objects that are in the mathematician’s domain. Yet every person on the street perceives math is about numbers. So even though numbers only scratch the surface of math and Mathematica, it makes sense to begin with their representation.

Mathematica supports four numerical types: Integer, Rational, Real, and Complex. In the following examples we use Mathematica’s comment notation ( *comment* ).

1         (*The integer one*)
1 / 2     (*The rational one half*)
1.2 * ^ 8 (*The real 1.2 x 10^8*)
3 + 2 I   (*The complex number 3+2i*)

There is no need to take my word that these expressions have the specified types. You can ask Mathematica to tell you using the function Head[] , which returns the head of an expression (i.e., head of a list).

In[2]:=  Head[1]
Out[2]=  Integer

In[3]:=  Head[1/2]
Out[3]=  Rational

In[4]:=  Head[1.2 ^ 8]
Out[4]=  Real

In[5]:=  Head[3 + 2 I]
Out[5]=  Complex

Although Mathematica does not internally store numbers as lists, it provides the illusion that a number has a head indicating its type. This is consistent with the fact that everything in Mathematica is an expression and every expression must have a head. It is also common for Mathematica to use the head to indicate type when constructing more complex objects. See 1.5 Working with Intervals, for example. If you are confused by this, for now, just think of Head as returning a type name when presented with an atomic expression (expressions that can’t be divided into subexpressions).

Exact and Approximate Results

Mathematica is unique in comparison to most mathematical tools and programming languages in that it will usually produce exact results unless you tell it otherwise. The following examples show the difference between exact and approximate results. 1.1 Controlling Precision and Accuracy and 1.2 Mixing Different Numerical Types show you how to make Mathematica use the appropriate form.

Exact results are displayed in their entirety when possible or symbolically when full display would be impossible due to the infinity of the exact representation.

Exact and Approximate Results

Approximate numeric results are represented in machine precision floating point by default. On most modern computers, this means double-precision floating-point numbers, which contain a total of 64 binary bits, typically yielding 16 decimal digits of mantissa. You can also specify numbers with greater than machine precision (see 1.1 Controlling Precision and Accuracy) but there is a performance cost: Mathematica must switch from the native hardware-based floating-point algorithms to software-based ones.

In[8]:= 3. ^ 1000
Out[8]= 1.322070819480807 x 10477

In[9]:= Sqrt[2.]
Out[9]= 1.41421

By adding a decimal point to a number, you force Mathematica to treat it as approximate. These approximate numbers will be machine precision by default, but there are several ways to force higher precision. 1.1 Controlling Precision and Accuracy and 1.2 Mixing Different Numerical Types in this chapter will elaborate on these differences.

Numerical Expressions

The previous examples show simple numerical expressions. In practice, Mathematica follows general mathematical notation, but in many cases this means that there are multiple ways to express the same thing. Let’s consider each of the common operations that arise in algebra. There are several ways to express multiplication, division, and other arithmetic operations. A single space between expressions (e.g., variables, numbers) implies multiplication, as is the typical convention among mathematicians. You can evaluate typeset mathematics using special symbols, such as ×. You can also use Full Form (e.g., Plus, Times, Divide), but for arithmetic this is unnecessarily verbose.

Numerical Expressions

The various representations are known as “forms” in Mathematica (e.g., InputForm, OutputForm, TraditionalForm, etc.). 1.7 Displaying Numbers in Alternate Forms shows you how to control what form is used for output of results. Controlling what form is used for input is a function of using the various features of the Mathematica frontend (palettes, shortcut keys, etc.). This book will not discuss the use of the frontend, since its main focus is programming, and there are numerous other resources (the best being the integrated help system) for mastering the frontend.

Numerical Approximations

Mathematica is famous for its symbolic abilities; however, when it comes to numerical methods it is also no slouch! The core functions for numerical solutions are NSum, NProduct, NSolve, NIntegrate, and NDSolve. These are covered in Chapter 10 and Chapter 12.

1.1 Controlling Precision and Accuracy

Problem

You want numerical results that are to a specified numerical precision and accuracy.

Solution

Use N[] to convert from exact to approximate form while controlling precision and accuracy to the desired amount.

In[19]:= N[1/5]
Out[19]= 0.2

You can explicitly specify the precision as a second argument to N[].

In[20]:= N[1/17,10]
Out[20]= 0.05882352941

You can also explicitly specify both the precision and accuracy, but this is less common. You might do this to guarantee a fixed number of decimal places independent of the size of the actual number.

In[21]:= N[{17, 1/17}, {Infinity, 10}]
Out[21]= {17.000000000, 0.0588235294}

To drive this point home, I ask you to consider the following. The first column uses fixed precision, whereas the second uses infinite precision and fixed accuracy.

    In[22]:= Table[With [{x = 10^n + 1 /17}, {N[x, 10], N[x, {Infinity, 10}]}],
               {n, 0, 5}] // TableForm
Out[22]//TableForm=
             1.058823529  1.058823529
             10.05882353  10.058823529
             100.0588235  100.058823529
             1000.058824  1000.058823529
             10000.05882  10000.0588235294
             100000.0588  100000.0588235294

Discussion

For most purposes, treat precision as the total number of digits in the decimal representation of a number and accuracy as the total number of digits after the decimal. As such, precision is a measure of relative uncertainty (given a precision p a larger number will have more uncertainty than a smaller number). Accuracy is an absolute measure of uncertainty because the number of places after the decimal is independent of the magnitude of the number. Typically you only need to control precision in most applications.

There are two common syntaxes for using N[]. You already saw the functional syntax in the solution section. The second uses Mathematica’s postfix notation. See the sidebar Mathematica Expressions for a discussion of postfix and other notations.

In[29]:= Sqrt[2] //N
Out[29]= 1.41421

It is common to use this notation to force Mathematica to convert an exact or symbolic result to an approximate result as the last step in a computation. When you use postfix notation, you can explicitly specify the precision, but it is a bit awkward.

In[30]:= Sqrt[2] //N[#, 10]&
Out[30]= 1.414213562

When you don’t specify precision, Mathematica uses MachinePrecision, which is a built-in symbol that denotes the precision native to your computer’s floating-point capabilities. The numerical value of MachinePrecision is stored in a variable $MachinePrecision.

In[31]:= $MachinePrecision
Out[31]= 15.9546

There is another notation that is less common but you may come across it in Mathematica output. If a literal number is displayed with a trailing ` (backtick) followed optionally by a number, this indicates the number is either in machine precision or is in the precision specified by the number following the backtick.

In[32]:= 20` (*20 in machine precision*)
Out[32]= 20.

In[33]:= 20`20 (*20 with high precision of 20 digits*)
Out[33]= 20.000000000000000000

In a complex expression with a lot of high-precision numbers, you can avoid specifying each precision individually by using SetPrecision[].

In[34]:= SetPrecision[20. + 1/3 * 12.3 / 37.8 + Pi, 20]
         (*All numbers will be set to a precision of 20.*)
Out[34]= 23.250058262055400604

Note

Mathematica Expressions

You may find it surprising that $MachinePrecision is not an integer. The reason stems from the formal definition of precision, which is derived from considering a number x and its uncertainty dx and using the expression - Log[10, dx/x]. Accuracy is defined as - Log[10, dx].

If you have an expression and need to know the precision or accuracy, you can use the following functions.

In[35]:= Precision[2.]
Out[35]= MachinePrecision

In[36]:= Precision[2'20]
Out[36]= 20.

Exact results have infinite precision.

In[37]:= Precision[Sqrt[2]]
Out[37]= ∞

In[38]:= Precision[Sqrt[2.]]
Out[38]= MachinePrecision

In[39]:= Accuracy[2.]
Out[39]= 15.6536

You are not guaranteed the accuracy you specify if the precision is too small.

In[40]:= Accuracy[N[30, {20, 20}]]
Out[40]= 18.5229

With enough precision, however, you will get accuracy.

In[41]:= Accuracy[N[30, {30, 20}]]
Out[41]= 20.

And precision can even be specified as infinite!

In[42]:= Accuracy[N[30, {Infinity, 20}]]
Out[42]= 20.

Mathematica also defines two internal variables: $MinPrecision, whose default value is zero, and $MaxPrecision, whose default value is plus infinity.

In[43]:= {$MinPrecision, $MaxPrecision}
Out[43]= {0, ∞}

You can control precision within a complex calculation (without using N[] on every intermediate result) by changing these values; however, you should only do so within a Block (a local context). For example, compare the difference between a calculation with automatic precision for intermediate results to the same calculation with fixed precision (obtained by making $MinPrecision == $MaxPrecision). Note that we must still start out the calculation with base values of at least $MinPrecision, otherwise the value will revert to the lowest precision, as explained in 1.2 Mixing Different Numerical Types.

In[44]:=  SetPrecision[(1 + Exp[Sqrt[2] + Sqrt[3]]) / 2^25, 32]
Out[44]=  7.226780742612584668840452114476x10–7

In[45]:=  Block[{$MinPrecision = 32, $MaxPrecision = 32},
           SetPrecision[(1 + Exp[Sqrt[2] + Sqrt[3]])/2^25, 32]]
Out[45]=  7.2267807426125846688404521144759x10–7

However, unless you have a very specific reason to control precision yourself, it is generally best to let Mathematica automatically handle this for you.

See Also

The Wolfram documentation for N[] is here: http://bit.ly/XVe2E.

Discussions of precision and accuracy can be found at http://bit.ly/15qq2N and http://bit.ly/icrh1 .

The most thorough discussions of precision and accuracy in Mathematica can be found in Chapter 8 of An Introduction to Programming with Mathematica (Cambridge University Press) and The Mathematica GuideBook for Numerics (Springer).

A nice essay by David Goldberg called “What Every Computer Scientist Should Know About Floating-Point Arithmetic” can be found at https://oreil.ly/5HuG4 .

1.2 Mixing Different Numerical Types

Problem

You need to predict what Mathematica will do with expressions containing mixed types and representations.

Solution

The general rule of thumb is that the least precise type will determine the type of the result.

Mixing exact values and symbols

When expressions containing exact numeric values (integers and rationals) are mixed with symbols, Mathematica will keep all results in the most general form, possibly reducing rationals to integers but leaving symbolic values in symbolic form.

Mixing exact values and symbols

Mixing exact values and approximate values

When an approximate value is used in an otherwise symbolic expression, it forces Mathematica to convert to approximate values.

In[48]:= (2.0 Pi) / 3 + Pi / 3
Out[48]= 3.14159

In[49]:= 1. + (2 Pi) / 3 + Pi / 3
Out[49]= 4.14159

Mixing values of different precision and accuracy

When you mix values of different precision and accuracy, the lower precision and accuracy will determine the result. For multiplication, the precision of the result will be exactly the minimum of the precision of each term, whereas the accuracy will be somewhat less.

In[50]:= x = N[Sqrt[2], 30] * N[Sqrt[3], 10]
Out[50]= 2.449489743

In[51]:= Precision[x]
Out[51]= 10.

In[52]:= Accuracy[x]
Out[52]= 9.61092

For addition, the accuracy of the result will be exactly the minimum of the accuracy of each term; the precision will be somewhat more.

In[53]:= x = N[Sqrt[5], {Infinity, 30}] + N[Sqrt[7], {Infinity, 10}]
Out[53]= 4.8818192886

In[54]:= Precision[x]
Out[54]= 10.6886

In[55]:= Accuracy[x]
Out[55]= 10.

Discussion

When mixing exact values with inexact values, it is possible to gain precision.

In[56]:= Precision[N[Sqrt[2], 20]]
Out[56]= 20.

In[57]:= Precision[2 +N[Sqrt[2], 20]]
Out[57]= 20.3828

The gain in precision will be greater when the magnitude of the exact number dominates that of the inexact number, as we see in this generated table.

Discussion

See Also

The most thorough discussions of Mathematica’s numerical rules can be found in Chapter 8 of An Introduction to Programming with Mathematica and The Mathematica GuideBook for Numerics.

1.3 Representing Numbers in Other Bases

Problem

Your application calls for a different numerical base than 10.

Solution

Mathematica uses notation of the form base^^digits to represent numbers in different bases. There must not be any internal whitespace in this representation.

In[59]:= 2^^101 (*Binary*)
Out[59]= 5

In[60]:= 16^^FFFF (*Hexidecimal*)
Out[60]= 65535

Discussion

In addition to expressing numbers in other bases, you can convert numbers to other bases with BaseForm[ digits, base ]. The base must be an integer between 2 and 36 when using either ^^ or BaseForm[]. Mathematica uses the letters a through z to represent digits higher than 10.

   In[61]:=  BaseForm[2^^1010101, 16]
Out[61]//BaseForm=
             5516

If you do math in another base, the output will still default to decimal, but you can use BaseForm to convert the output of a function to hex.

   In[62]:= 16^^A0 + 16^^0F // BaseForm[#, 16] &
Out[62]//BaseForm=
             af16

    In[63]:= Hash["Hello, my name is Sal", "MD5"] // BaseForm[#, 16] &
Out[63]//BaseForm=
             a275144453239f0279228469f229688116

You can also convert real and complex numbers to other bases.

Discussion

See Also

1.5 Working with Intervals shows how to extract digits of a number in alternate bases.

1.4 Extracting the Digits of a Number

Problem

You want to extract the individual digits of a number to manipulate them individually.

Solution

The functions IntegerDigits[] and RealDigits[] make this task easy.

IntegerDigits[] returns a list of digits in base 10. See the Discussion section, next, for additional options.

In[66]:= IntegerDigits[12345]
Out[66]= {1, 2, 3, 4, 5}

RealDigits[] returns a two-item list with the first item being the digits in base 10 and the second being the position of the decimal point. See the Discussion section for additional options. First consider the digits display with N[] alone.

In[67]:= N[1/31]
Out[67]= 0.0322581

Notice how RealDigits[] automatically extracts more precision to return the number of digits necessary to get to the point at which they begin to repeat in the decimal expansion.

In[68]:= RealDigits[N[1 / 31], 10]
Out[68]= {{3, 2, 2, 5, 8, 0, 6, 4, 5, 1, 6, 1, 2, 9, 0, 3}, -1}

Discussion

Both RealDigits[] and IntegerDigits[] take the desired base and the number of desired digits (length) as optional second and third arguments, respectively.

   In[69]:=  12 !
   Out[69]=  479 001 600

   In[70]:=  IntegerDigits[12!, 10, 5]
   Out[70]=  {0, 1, 6, 0, 0}

   In[71]:=  12! // BaseForm[#, 16] & (*Consider 12! in base 16.*)
Out[71]//BaseForm=
             1c8cfc0016

   In[72]:=  IntegerDigits[12!, 16]   (*Notice how IntegerDigits
              with base 16 gives the digit values in base 10.*)
   Out[72]=  {1, 12, 8, 12, 15, 12, 0, 0}

   In[73]:=  IntegerDigits[12!, 16] // BaseForm[#, 16]&
              (*But you can easily force them to base 16.*)
Out[73]//BaseForm=
             {116, c16, 816, c16, f16, c16, 016, 016}

RealDigits can take an additional fourth argument that specifies where in the decimal expansion to start. If b is the base, then the fourth argument n means to start the counting at the coefficient signified by b^n . The following examples should clarify.

In[74]:=  N[Pi, 10]      (*Pi to 10 digits of precision.*)
Out[74]=  3.141592654

In[75]:=  RealDigits[Pi, 10, 3]
          (*Extract first three digits. Decimal place is indicated as 1.*)
Out[75]=  {{3, 1, 4}, 1}

Start at 10^-2 = 0.01, or the second digit after the decimal.

In[76]:=  RealDigits[Pi, 10, 3, -2]
          (*Extract third to fifth digit. Decimal place is indicated as -2.*)
Out[76]=  {{4, 1, 5}, -1}

Start at 10^-5 = 0.00001, or the fifth digit after the decimal.

   In[77]:=  RealDigits [Pi, 10, 3, -5]
   Out[77]=  {{9, 2, 6}, -4}

   In[78]:=  N[Pi,10] // BaseForm[#, 2] &
Out[78]//BaseForm=
             11.00100100001111110110101010001002

Here we get the digits of pi in base 2.

In[79]:=  RealDigits[Pi, 2, 5, -2]
Out[79]=  {{0, 1, 0, 0, 1}, -1}

Here is an interesting application in which IntegerDigits is combined with the Tuples function and a bit of pattern matching to get all n digits without calling IntegerDigits[] more than once. We used Short to elide the full list. (Short places <<n>> in the output to indicate n missing items.)

   In[80]:=  Tuples[IntegerDigits[43210], 4] // Short[#, 4] &
Out[80]//Short=
             {{4, 4, 4, 4}, {4, 4, 4, 3}, {4, 4, 4, 2}, {4, 4, 4, 1}, {4, 4, 4, 0}, {4, 4, 3, 4},
              {4, 4, 3, 3}, {4, 4, 3, 2}, {4, 4, 3, 1}, {4, 4, 3, 0}, {4, 4, 2, 4},
              {4, 4, 2, 3}, {4, 4, 2, 2}, {4, 4, 2, 1}, {4, 4, 2, 0}, {4, 4, 1, 4},
              {4, 4, 1, 3}, {4, 4, 1, 2}, {4, 4, 1, 1}, {4, 4, 1, 0}, {4, 4, 0, 4},
              {4, 4, 0, 3}, {4, 4, 0, 2}, <<579>>,   {0, 0, 4, 2}, {0, 0, 4, 1}, {0, 0, 4, 0},
              {0, 0, 3, 4}, {0, 0, 3, 3}, {0, 0, 3, 2}, {0, 0, 3, 1}, {0, 0, 3, 0},
              {0, 0, 2, 4}, {0, 0, 2, 3}, {0, 0, 2, 2}, {0, 0, 2, 1}, {0, 0, 2, 0},
              {0, 0, 1, 4}, {0, 0, 1, 3}, {0, 0, 1, 2}, {0, 0, 1, 1}, {0, 0, 1, 0},
              {0, 0, 0, 4}, {0, 0, 0, 3}, {0, 0, 0, 2}, {0, 0, 0, 1}, {0, 0, 0, 0}}

If you do not want the cases with leading zeros, you can use DeleteCases as follows.

   In[81]:=  DeleteCases[Tuples[IntegerDigits[43210], 4],
               {z__ /; z == 0, n__}] //  Short[#, 4] &
Out[81]//Short=
             {{4, 4, 4, 4}, {4, 4, 4, 3}, {4, 4, 4, 2}, {4, 4, 4, 1}, {4, 4, 4, 0}, {4, 4, 3, 4},
              {4, 4, 3, 3}, {4, 4, 3, 2}, {4, 4, 3, 1}, {4, 4, 3, 0}, {4, 4, 2, 4},
              {4, 4, 2, 3}, {4, 4, 2, 2}, {4, 4, 2, 1}, {4, 4, 2, 0}, {4, 4, 1, 4},
              {4, 4, 1, 3}, {4, 4, 1, 2}, {4, 4, 1, 1}, {4, 4, 1, 0}, {4, 4, 0, 4},
              {4, 4, 0, 3}, {4, 4, 0, 2}, <<454>>, {1, 0, 4, 2}, {1, 0, 4, 1}, {1, 0, 4, 0},
              {1, 0, 3, 4}, {1, 0, 3, 3}, {1, 0, 3, 2}, {1, 0, 3, 1}, {1, 0, 3, 0},
              {1, 0, 2, 4}, {1, 0, 2, 3}, {1, 0, 2, 2}, {1, 0, 2, 1}, {1, 0, 2, 0},
              {1, 0, 1, 4}, {1, 0, 1, 3}, {1, 0, 1, 2}, {1, 0, 1, 1}, {1, 0, 1, 0},
              {1, 0, 0, 4}, {1, 0, 0, 3}, {1, 0, 0, 2}, {1, 0, 0, 1}, {1, 0, 0, 0}}

The inverse of IntegerDigits[] is FromDigits[].

In[82]:= FromDigits[IntegerDigits[987654321]]
Out[82]= 987 654 321

In[83]:= FromDigits[IntegerDigits[987654321, 2], 2] (*Base 2*)
Out[83]= 987 654 321

FromDigits[] has the added capability of converting strings and roman numerals.

In[84]:= FromDigits["4750"] + 1
Out[84]= 4751

In[85]:= FromDigits["MMXIX", "Roman"] – 10
Out[85]= 2009

IntegerString[] is used to convert back to string form. I use InputForm only so the quotes are displayed.

   In[86]:=  IntegerString[4750] //InputForm
Out[86]//InputForm=
             "4750"

   In[87]:=  IntegerString[2009, "Roman"] // InputForm
Out[87]//InputForm=
             "MMIX"

1.5 Working with Intervals

Problem

You need to compute with data subject to measurement errors and you need the greatest possible estimate on the final error.

Solution

As an alternative to doing math directly on numbers, Mathematica allows you to do math on intervals that define the uncertainty in a value.

In[88]:= Clear[error1, error2, mass, velocity, kineticEnergy];
         error1 = 0.01; error2 = 0.005;
         mass = Interval[{1.10 - error1, 1.10 + error1}];
         velocity = Interval[{7.50 - error2, 7.50 + error2}];
         kineticEnergy = 1/2 mass velocity ^ 2
Out[92]= Interval[{30.6154, 31.2604}]

By representing them as intervals, we express the idea that there are some known errors in the measurement of the value of mass and velocity. We would like to understand what that means in terms of the value we compute for kinetic energy.

You can see that the resulting error range is magnified by the combination of each error and the squaring.

In[93]:= Subtract @@ kineticEnergy[[1]] //
          Abs (*This computes the size of the interval.*)
Out[93]= 0.645

If there were only a single interval of uncertainty, the range would be smaller.

In[94]:= Clear[error1, mass, velocity, kineticEnergy];
         error1 = 0.01;
         mass = Interval[{1.10 - error1, 1.10 + error1}];
         velocity = 7.5;
         kineticEnergy = 1/2 mass velocity^2
Out[98]= Interval[{30.6562, 31.2188}]

In[99]:= Subtract @@ kineticEnergy[[1]] // Abs
Out[99]= 0.5625

Discussion

Intervals are objects with head Interval and a sequence of one or more lists that represent segments of the interval. Typically there is one list, but non-overlapping intervals can be expressed using two or more lists.

In[100]:= Interval[{1, 2}]
Out[100]= Interval[{1, 2}]

In[101]:= Interval[{1, 2}, {3, 4}]
Out[101]= Interval[{1, 2}, {3, 4}]

Intervals will automatically reorder themselves so that the least value is first.

In[102]:= Interval[{2, 1}]
Out[102]= Interval[{1, 2}]

In[103]:= Interval[{4, 3}, {2, 1}]
Out[103]= Interval[{1, 2}, {3, 4}]

Naturally, the standard mathematical operations for scalars work on intervals as well.

Discussion

There are also functions specifically for working with intervals. IntervalUnion[] gives the interval representing set of all points of the input intervals. IntervalIntersection[] gives the interval in common among the inputs and IntervalMemberQ[] tests if a value belongs to an interval.

There are some cases in which Mathematica functions can return intervals. Consider the problem of finding the limit of an oscillating function at a critical value.

Discussion

See Also

Papers and FAQs (as well as a movie) related to the theory of interval math can be found at https://oreil.ly/LmZ4N.

1.6 Converting Between Numerical Types

Problem

You have a number of one type and need it represented in another type.

Solution

Conversion from rational to integer happens automatically, when possible.

In[111]:= Head[4/2]
Out[111]= Integer

Conversion of rational to integer can be forced by using Floor[], Ceiling[], and Round[]. (Numbers of the form x .5 are rounded toward the nearest even integer.)

In[112]:= Floor[5/2]
Out[112]= 2

In[113]:= Ceiling[5/2]
Out[113]= 3

In[114]:= Round[5/2]
Out[114]= 2

In[115]:= Round[7/2]
Out[115]= 4

We already saw in 1.1 Controlling Precision and Accuracy how N[] can be used to convert exact values and symbolic constants to approximate real numbers. Rationalize[] is how you convert from approximate values to exact.

Solution

The single argument version of Rationalize will only succeed if a sufficiently close (see Discussion section, next) rational number exists.

In[117]:= Rationalize[3.1415927]
Out[117]= 3.14159

You can provide a second argument specifying your tolerance for error, in which case the operation will always succeed.

Solution

And you can force an exact rational by indicating a maximum error of zero.

Solution

Discussion

On the surface, the solutions here are rather simple. In day-to-day usage, numeric conversion will not present many challenges. However, there are subtle issues and interesting theory underlying the apparent simplicity. Let’s consider rounding. Suppose you need to round a set of numbers, but the numbers still must satisfy some constraint after the rounding. Consider percentages or probabilities. One would want percentages to still add to 100 and probabilities to still sum to 1. Another context is in statistics, where we want to round while preserving certain statistical properties, such as the variance. Various forms of stochastic rounding can be used in these cases. One form of stochastic rounding that gives good results is the unbiased rounding rule. According to this rule, a number of the form x.v is rounded up with the probability v /10 and rounded down with probability (10-v)/10. So, for example, 10.5 would have equal probability of going to 10 as to 11, whereas 10.85 would have probability of 0.85 of rounding up and 0.15 of rounding down.

In[120]:= UnbiasedRound[x_] := Block[{whole = Floor[x], v},
            v = 10 * (x - whole); whole + Floor[v/10 + RandomReal[]]]

In[121]:= Table[UnbiasedRound[10.5], {20}]
Out[121]= {11, 11, 10, 11, 10, 10, 10, 11, 11, 11, 10, 11, 11, 10, 10, 11, 11, 11, 11, 11}

In[122]:= Table[UnbiasedRound[10.1], {20}]
Out[122]= {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 10, 10, 10, 10, 11, 10, 10, 10}

In[123]:= Table[UnbiasedRound[10.8], {20}]
Out[123]= {11, 11, 11, 10, 11, 11, 11, 11, 11, 10, 11, 10, 11, 11, 10, 11, 11, 11, 11, 11}

The main disadvantage of stochastic rounding is that the results are not repeatable.

See Also

An Examination of the Effects of Rounding on the Quality and Confidentiality of Tabular Data by Lawrence H. Cox and Jay J. Kim ( https://oreil.ly/6Saie ).

1.7 Displaying Numbers in Alternate Forms

Problem

You don’t like the format that Mathematica chooses to display a particular numerical result.

Solution

Use one of the alternative forms: AccountingForm, EngineeringForm, NumberForm, PaddedForm, and ScientificForm. The default form is usually the most compact way to represent the number, but if you are outputting values that have specific user expectations or if you are trying to convey a specific accuracy, you may want to force a different form.

In[124]:= number = 3.50 * 1000000
Out[124]= 3.5x106

Accounting form does not use scientific notation and shows negative numbers in parentheses. Here it is traditional to use the form as a postfix (//) operation.

  In[125]:=  number // AccountingForm
Out[125]//AccountingForm=
             3500000.

  In[126]:=  -number // AccountingForm
Out[126]//AccountingForm=
             (3500000.)

Alternatively, NumberForm allows you to control the digits of precision and the number of digits after the decimal.

  In[127]:=  NumberForm[number, {6, 4}]
Out[127]//NumberForm=
             3.5000x106

Discussion

Forms have an extensive set of options to provide fine-grained control over the output. Here I use AccountingForm to display a column of numbers. DigitBlock specifies the grouping factor and NumberPadding allows control of the characters used to pad out the display on the left (shown here as spaces) and right (shown as zeros).

Discussion

Contrast this to AccountingForm without the options.

  In[129]:=  AccountingForm [Column [{100000.00, 1000000.00, 10000000.00}]]
Out[129]//AccountingForm=
             100000.
             1000000.
             10000000.

PaddedForm is convenient when all you want to do is pad out a number with specific characters on the left and right. This is often a useful operation prior to conversion to a string to generate fixed-length identifiers.

Discussion

EngineeringForm forces exponents in multiples of three, provided an exponent of at least three is required.

  In[132]:=  {10.0, 100.0, 1000.0, 10 000.0, 100 000.0, 1 000 000.0} // EngineeringForm
Out[132]//EngineeringForm=
             {10., 100., 1.×103, 10.×103, 100.×103, 1.×106}

ScientificForm always shows numbers with one digit before the decimal and adjusts the exponent accordingly.

  In[133]:=  {10.0, 100.0, 1000.0, 10 000.0, 100 000.0, 1 000 000.0} // ScientificForm
Out[133]//ScientificForm=
             {1.×101, 1.×102, 1.×103, 1.×104, 1.×105, 1.×106}

You can use the option NumberFormat to get precise control of the display. NumberFormat specifies a function (see Chapter 2 for details) that accepts up to three arguments for the mantissa, base, and exponent. Here is an example that displays numbers like a calculator might. Here, the function uses Row to format the mantissa and exponent (it ignores the base).

Discussion

See Also

You can find information and examples on all these forms and their options in the Wolfram documentation under tutorial/OutputFormatsForNumbers.

Get Mathematica Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.