# [Tutor] Rounding to n significant digits?

Tim Peters tim.peters at gmail.com
Sat Jul 3 15:49:09 EDT 2004

```[Dick Moores]
...
> But I realize that I don't need to return a float. Just the string will
> do. Therefore, this revision of your function will do exactly what I was
> thinking of, even if I didn't say so:
>
> """
> def round_to_n(x, n):
>             if n < 1:
>                 raise ValueError("number of significant digits must be >= 1")
>             # Use %e format to get the n most significant digits, as a string.
>             format = "%." + str(n-1) + "e"
>             as_string = format % x
>             return as_string
> """
> print round_to_n(123.456789, 4)
> print round_to_n(.000000123456789, 2)
> print round_to_n(123456789, 5)
>
> That displays
>
> 1.235e+002
> 1.2e-007
> 1.2346e+008  (this is much better than getting the ".0" of 123460000.0,
> which implies accuracy to 10 significant digits instead of 5.)

Then it's time to learn about one of the more obscure features of
string formats:  if you put an asterisk in a string format where a
precision specifier is expected, the actual precision to use will be
taken from the argument tuple.  I realize that's confusing; that's why
I called it obscure <wink>.  It should be clearer from this rewrite of
your rewrite of my original round_to_n function:

def round_to_n(x, n):
if n < 1:
raise ValueError("number of significant digits must be >= 1")
return "%.*e" % (n-1, x)

That's probably the end of the line for this problem <wink>.

A related but harder problem is to get a string rounded to n
significant digits, but where the exponent is constrained to be a
multiple of 3.  This is often useful in engineering work.  For
example, in computer work, 1e6 and 1e3 are natural units (mega and
kilo), but 1e4 isn't -- if I have 15,000 of something, I want to see
that as 15e3, not as 1.5e4.  I don't know an easy way to get that in
Python (or in most other programming languages).

```