Recently, one of my colleagues needed to print a collection of measurements with uncertainties in scientific rounding to publish them in a paper. If there are only two or three fixed numbers, it’s probably easier to do this by hand. As soon as there are more numbers or if the numbers might change in the future, it is more convenient to have a method which formats the number and the uncertainty automatically.

My own Python package pyveu easily achieves scientific rounding, however before I come to concrete examples, I should first explain what I mean by scientific rounding.

In high school, we learn to quote results with a fixed number of significant digits, usually three or four. For example, if we the calculator says 252,083.567493, we are supposed to round the final result to a fixed number of significant digits. In the case of three significant digits, the result should be 252,000.

Why three or four significant digits? Well, good point. This is entirely arbitrary and not scientific at all. To be strict, measured values only make sense when quoted with an uncertainty. The uncertainty is part of the measurement and gives information about the accuracy1 of the measurement. The uncertainty of the measurement depends on the measurement procedure and the measurement equipment. For example, if you measure the weight of bullion with a precision scale you can quote more significant digits compared to a kitchen scale. For example, if your measurement procedure has an uncertainty of 0.5g, the measured value should include all digits including the 0.1 digit–independently of the magnitude of the measured value. However, if your measurement accuracy is 0.1g, you probably won’t be able to measure the weight of a whole cruise ship.

The measurement uncertainty determines the number of significant digits to be quoted. However, this does not tell us how to round the uncertainty itself. Assume a measurement uncertainty of 0.672360544. The first point to note here is that the measurement uncertainties are usually estimated and sometimes based on some assumptions. A general rule is that the uncertainty should have only one or two significant digits (think about the uncertainty on the uncertainty estimate itself). Two digits are in many cases already too precise. A single digit is in many cases too coarse. For example in the case of a single digit, if the measurement uncertainty is estimated to be 14.9 g, then we should round this to 10 g. The difference between 14.9 g and 10 g is about 30%.

It is general scientific practice to interpolate between a single and two significant digits for the uncertainty estimate as follows. If the most significant digits of the uncertainty are between 10 and 20 (or 35, the threshold depends on the scientific community), then use two digits for the uncertainty, otherwise, use only one digit. The following examples illustrate this rule

13.23     -> 13     # two significant digits
1930.234  -> 2000   # single significant digit
0.00384   -> 0.004  # single significant digit
0.75      -> 0.8    # single significant digit
1.7       -> 1.7    # two significant digits

If we combine the uncertainty of the measurement with the actual value of the measurement, we should round the measurement to the last significant digit of the rounded uncertainty.

Since we have established the rules, we can think about implementing these rules in Python. There are a couple of pitfalls. In Python 3, the round() method rounds to even in case of a tie. This means round(0.5) evaluates to 0, whereas round(1.5) evaluates to 2. This is definitively not what we want. Also when rounding to a specific precision, you are likely to encounter rounding errors, due to the floating point representation of numbers in Python.

As I said initially, there is an easy-to-use solution. The Python package pyveu applies all the rule mentioned above and takes care of all the corner cases.

For example, if we have a measurement with an uncertainty of 0.034543, we can use the following lines to format measurement results:

from pyveu import Quantity

Quantity(12.5468431651, 0.034543).round()  # returns '12.55' and '0.03'
Quantity(182.5468431651, 0.034543).round()  # returns '182.55' and '0.03'

If the uncertainty is reduced by a factor of three, the same measurements are formatted as follows.

from pyveu import Quantity

Quantity(12.5468431651, 0.034543 / 3).round()  # returns '12.547' and '0.012'
Quantity(182.5468431651, 0.034543 / 3).round()  # returns '182.547' and '0.012'

The Quantity.round() method takes the optional argument significant_digits which controls the number of significant digits of the uncertainty. If this is set to 1, the uncertainty will always have one significant digit. If this is set to 2, the uncertainty will always have two significant digits. Any non-integer number will interpolate between two numbers of digits. For example, if this is set to 1.35, the uncertainty will have two digits if the most significant digits are below 35. If the most significant digits of the uncertainty are above 35, only one digit is returned. The default is 1.2.

  1. In this article, I do not make any distinction between the terms accuracy and precision, or statistical and systematic uncertainties.