Most users probably want to use `SetPrecision`

, which preserves extra digits and automagically handles fractional digits of precision. However, in this case, we need to somehow override this behavior.

I'll use a custom object, `sigFigNumber`

. First I'll define how it's displayed.

```
Format[sigFigNumber[s_, d_]] := N[s, d]
```

So we can see that sigFigNumber has two fields: the first one is the significand, and the second is the desired number of digits of precision. But we need a way to get this object!

```
createSigFigNumber[s_, d_] :=
sigFigNumber[
If[d == \[Infinity], s, Round[s, 10^(-d + Floor[Log10[Abs[s]]] + 1)]], d]
createSigFigNumber[s_] :=
createSigFigNumber[SetPrecision[s, \[Infinity]],
Floor[Log10[Abs[s]]] - Floor[-Precision[s] + Log10[Abs[s]]]]
```

We can use the two-argument form of `createSigFigNumber`

to round a number to the specified number of digits. If we omit the number of digits, then the second function is invoked, which automatically determines the number of digits from the precision of the number. Let's look at some examples now.

```
createSigFigNumber[1.234, 3] (* 1.23, sigFigNumber[123/100, 3] *)
createSigFigNumber[1.23`3] (* 1.23, sigFigNumber[123/100, 3] *)
createSigFigNumber[1] (* 1, sigFigNumber[1, Infinity] *)
createSigFigNumber[Pi] (* \[Pi], sigFigNumber[Pi, Infinity] *)
```

We can see that the significand of `sigFigNumber`

is stored in exact form, rounded to the correct decimal place, but is displayed as a decimal (also with the correct number of decimal places showing). Also, exact numbers have a precision of `Infinity`

and so are left unrounded.

Now let's define some functions to do math with these numbers. I'll just give the examples of multiplication (easy) and addition (harder).

```
sigFigNumber[s1_, d1_] * sigFigNumber[s2_, d2_] ^:=
createSigFigNumber[s1 s2, Min[d1, d2]]
sigFigNumber[s1_, d1_] + sigFigNumber[s2_, d2_] ^:=
createSigFigNumber[s1 + s2,
Floor[Log10[Abs[s1 + s2]]] -
Max[Floor[Log10[Abs[s1]]] - d1, Floor[Log10[Abs[s2]]] - d2]]
```

First note that I am using upvalues to define the behavior of operators on this new object.

For multiplication the problem is simple, the resulting number of significant figures is simply the minimum of the two input numbers. For addition the problem is more complex, requiring us to first convert the precisions to accuracies, find the largest (highest-value last decimal place) and then finally convert back to precision. Now for some examples:

```
x = createSigFigNumber[1.23, 3] (* 1.23 *)
y = createSigFigNumber[0.45, 2] (* 0.45 *)
z = createSigFigNumber[0.6, 1] (* 0.6 *)
x y (* 0.55 *)
y z (* 0.3 *)
z x (* 0.7 *)
x + y (* 1.68 *)
y + z (* 1.0 *)
z + x (* 1.8 *)
```

This looks pretty good, although I see one possible problem: you might expect `y + z`

to return `1.1`

(the unrounded value is `1.05`

). The Mathematica documentation states that "`Round`

rounds numbers of the form `x.5`

toward the nearest even integer." In this case, it's effectively rounding `10.5`

, and the nearest *even* integer is `10`

, not `11`

, resulting in `1.0`

instead of `1.1`

. So if your students use round-towards-even the results will match. Otherwise you will have to re-write the `Round`

function to something like this:

```
sigFigRound[a_, b_] :=
b (IntegerPart[a/b] +
If[Abs[FractionalPart[a/b]] >= 1/2, Sign[a], 0])
sigFigRound[105/100, 1/10] (* 11/10 *)
```

You'll have to write functions to handle every operation. However, you have a choice. In order to handle division/subtraction you can either write functions for `Divide`

and `Subtract`

, *or* you can write functions for `Times`

and `Power`

. See what Mathematica does internally:

```
a - b // FullForm (* Plus[a, Times[-1, b]] *)
```

Is there anything wrong with using

– Cameron Murray – 2015-01-25T04:52:19.963`N[#,3]&`

? http://reference.wolfram.com/language/ref/N.html?q=NSorry I don't understand what you mean, can you explain in more detail? – George Papadopoulos – 2015-01-25T05:14:05.250

In my opinion your question would be much improved if you were to edit out the ranting and just present the numerics problem you want to address. – m_goldberg – 2015-01-25T05:14:58.310

2If you compute N[Pi,3] you'll get 3.14. But copy that output and paste it back into an input field to see that many more digits are retained. This is a perennial annoyance with

Mathematica, and documented many places. – David G. Stork – 2015-01-25T05:15:50.230Just so we are all clear, do you know the difference between the precision of reals used in Mathematica calculations and the print precision used for display? – Mike Honeychurch – 2015-01-25T05:16:10.147

Have you looked at

– m_goldberg – 2015-01-25T05:25:53.057`NumberForm`

?@m_goldberg sorry, fair point, done. Was that the reason for the negative downvote on my question?

@DavidG.Stork I have been searching but have not found it documented, only people trying to work around it, not blatantly stating that "this is a perennial annoyance with

Mathematica". Thanks for letting me know of the persisting issue though.@MikeHoneychurch Yes I know the difference, and that is why the use of

`N`

is useless.@m_goldberg yes I have, but the output is not something that can be worked with mathematically so that's also useless for computational purposes. – George Papadopoulos – 2015-01-25T05:51:43.903

I down voted because of the ranting. Now that it's gone, I removed my down vote. – m_goldberg – 2015-01-25T06:25:31.187

I must say the way you have staged your question it means that nearly every system has problems, as you would need to use fixed point arithmetic. – joojaa – 2015-01-31T09:58:37.273

@joojaa actually I think that the selected answer works in all cases. – George Papadopoulos – 2015-02-06T02:05:26.007