Skip to content

Floating point and SI units

Øystein Bjørndal edited this page Sep 29, 2013 · 2 revisions

This page is for working with floating point numbers, where additional tricks are shown for numbers with SI units.

Say you want to write something like this:

\begin{pylabcode}
R = 50
V = 1.42
I = V/R
\end{pylabcode}
The current through a \pylab{R} $\Omega$ resistor is \pylab{I} $A$

The result would then be:

The current through a 50 $\Omega$ resistor is 0.028399999999999998 $A$

which isn't very attractive. To get the right number of significant digits, the following might be useful:

def n(num, sig=3):
  f = '%.' + str(sig) + 'g' 
  ret = f % num
  return ret

Which would produce 0.0285 instead.

Larger numbers

Scientific notation

For larger number one can either add the following in the latex preamble:

\providecommand{\e}[1]{\ensuremath{\times 10^{#1}}} % scientific notation 

and adjust the python code to

def n(num, sig=3):
  f = '%.' + str(sig) + 'g' 
  ret = f % num
  if 'e' in ret:
     ret = ret.replace('e', r'\e{'
     ret += '}'
  return ret

Which might produce something like 4.2x10^10.

SI units

Alternatively one might want numbers to have the correct SI prefix (G, M, k, m, micro), in which case the following can be utilized.

from math import log10
def n(num, sig=3):
  f = '%.' + str(sig) + 'g' 
  ret = f % num
  return ret
def eUnit(num):
  ''' Takes a float n and returns scaled version and a SI prefix. Invalid input returns the input'''
  unit = {9: 'G', 6: 'M', 3: 'k', 0: '',
         -3: 'm', -6: '\\textmu', -9: 'n', -12: 'p', -15: 'f', -18: 'a', -21: 'z'} 
  try:
    x = int(log10(n)//3)*3
    u = unit[x]
  except (ValueError, KeyError):
    x = 0
  return n/10**x, unit[x]
def si(num, unit='', sig=3, auto_scale=True):
  if auto_scale:
    num, siPrefix = eUnit(num)
    siPrefix = siPrefix.replace('$', '')
  else:
    siPrefix = ''
  num = n(num, sig=sig)
  res = r'\SI{%s}{%s%s}' % (num, siPrefix, unit)

Which requires the following in the latex preamble:

\usepackage{siunitx}

The above example would then be

The current through a \pylab{si(R, r'\ohm')} resistor is \pylab{si(I, r'A')}.

Producing

The current through a \SI{50}{\ohm} resistor is \SI{28.4}{mA}

If you find ourself typing this allot, you can define your own latex command like this

\providecommand{\psi}[1]{\pylab{si(#1)}}
The current through a \psi{R, r'\ohm'} resistor is \psi{I, r'A'}.
Clone this wiki locally