Scientific rounding with pyveu
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 accuracy^{1} 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 easytouse 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
noninteger 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
.

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