Source code for chempy.printing.numbers

# -*- coding: utf-8 -*-
from __future__ import (absolute_import, division, print_function)

from math import log10, floor

from ..units import html_of_unit, latex_of_unit, unicode_of_unit, to_unitless, unit_of
from ..util.parsing import _unicode_sup


[docs]def roman(num): """ Examples -------- >>> roman(4) 'IV' >>> roman(17) 'XVII' """ tokens = 'M CM D CD C XC L XL X IX V IV I'.split() values = 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 result = '' for t, v in zip(tokens, values): cnt = num//v result += t*cnt num -= v*cnt return result
def _mag(num): return int(floor(log10(abs(num)))) def _float_str_w_uncert(x, xe, precision=2): """ Prints uncertain number with parenthesis Parameters ---------- x : nominal value xe : uncertainty precision : number of significant digits in uncertainty Examples -------- >>> _float_str_w_uncert(-9.99752e5, 349, 3) '-999752(349)' >>> _float_str_w_uncert(-9.99752e15, 349e10, 2) '-9.9975(35)e15' >>> _float_str_w_uncert(3.1416, 0.029, 1) '3.14(3)' >>> _float_str_w_uncert(3.1416e9, 2.9e6, 1) '3.142(3)e9' Returns ------- shortest string representation of "x +- xe" either as ``x.xx(ee)e+xx`` or ``xxx.xx(ee)`` Notes ----- The code in this function is from a question on StackOverflow: http://stackoverflow.com/questions/6671053 written by: Lemming, http://stackoverflow.com/users/841562/lemming the code is licensed under 'CC-WIKI'. (see: http://blog.stackoverflow.com/2009/06/attribution-required/) """ # base 10 exponents x_exp = int(floor(log10(abs(x)))) xe_exp = int(floor(log10(abs(xe)))) # uncertainty un_exp = xe_exp-precision+1 un_int = round(xe*10**(-un_exp)) # nominal value no_exp = un_exp no_int = round(x*10**(-no_exp)) # format - nom(unc)exp fieldw = x_exp - no_exp fmt = '%%.%df' % fieldw result1 = (fmt + '(%.0f)e%d') % (no_int*10**(-fieldw), un_int, x_exp) # format - nom(unc) fieldw = max(0, -no_exp) fmt = '%%.%df' % fieldw result2 = (fmt + '(%.0f)') % (no_int*10**no_exp, un_int*10**max(0, un_exp)) # return shortest representation if len(result2) <= len(result1): return result2 else: return result1 def _number_to_X(number, uncertainty, unit, fmt, unit_fmt, fmt_pow_10, space=' '): uncertainty = uncertainty or getattr(number, 'uncertainty', None) unit = unit or unit_of(number) integer_one = 1 if unit is integer_one: unit_str = '' mag = number else: unit_str = space + unit_fmt(unit) mag = to_unitless(number, unit) if uncertainty is not None: uncertainty = to_unitless(uncertainty, unit) if uncertainty is None: if fmt is None: fmt = 5 if isinstance(fmt, int): flt = ('%%.%dg' % fmt) % mag else: flt = fmt(mag) else: if fmt is None: fmt = 2 if isinstance(fmt, int): flt = _float_str_w_uncert(mag, uncertainty, fmt) else: flt = fmt(mag, uncertainty) if 'e' in flt: significand, mantissa = flt.split('e') return fmt_pow_10(significand, mantissa) + unit_str else: return flt + unit_str def _latex_pow_10(significand, mantissa): if significand in ('1', '1.0'): fmt = '10^{%s}' else: fmt = significand + r'\cdot 10^{%s}' return fmt % str(int(mantissa))
[docs]def number_to_scientific_latex(number, uncertainty=None, unit=None, fmt=None): r""" Formats a number as LaTeX (optionally with unit/uncertainty) Parameters ---------- number : float (w or w/o unit) uncertainty : same as number unit : unit fmt : int or callable Examples -------- >>> number_to_scientific_latex(3.14) == '3.14' True >>> number_to_scientific_latex(3.14159265e-7) '3.1416\\cdot 10^{-7}' >>> import quantities as pq >>> number_to_scientific_latex(2**0.5 * pq.m / pq.s) '1.4142\\,\\mathrm{\\frac{m}{s}}' >>> number_to_scientific_latex(1.23456, .789, fmt=2) '1.23(79)' """ return _number_to_X(number, uncertainty, unit, fmt, latex_of_unit, _latex_pow_10, r'\,')
def _unicode_pow_10(significand, mantissa): if significand in ('1', '1.0'): result = u'10' else: result = significand + u'·10' return result + u''.join(map(_unicode_sup.get, str(int(mantissa))))
[docs]def number_to_scientific_unicode(number, uncertainty=None, unit=None, fmt=None): u""" Formats a number as unicode (optionally with unit/uncertainty) Parameters ---------- number : float (w or w/o unit) uncertainty : same as number unit : unit fmt : int or callable Examples -------- >>> number_to_scientific_unicode(3.14) == u'3.14' True >>> number_to_scientific_unicode(3.14159265e-7) == u'3.1416·10⁻⁷' True >>> import quantities as pq >>> number_to_scientific_unicode(2**0.5 * pq.m / pq.s) '1.4142 m/s' """ return _number_to_X(number, uncertainty, unit, fmt, unicode_of_unit, _unicode_pow_10)
def _html_pow_10(significand, mantissa): if significand in ('1', '1.0'): result = '10<sup>' else: result = significand + '&sdot;10<sup>' return result + str(int(mantissa)) + '</sup>'
[docs]def number_to_scientific_html(number, uncertainty=None, unit=None, fmt=None): r""" Formats a number as HTML (optionally with unit/uncertainty) Parameters ---------- number : float (w or w/o unit) uncertainty : same as number unit : unit fmt : int or callable Examples -------- >>> number_to_scientific_html(3.14) == '3.14' True >>> number_to_scientific_html(3.14159265e-7) '3.1416&sdot;10<sup>-7</sup>' >>> number_to_scientific_html(1e13) '10<sup>13</sup>' >>> import quantities as pq >>> number_to_scientific_html(2**0.5 * pq.m / pq.s) '1.4142 m/s' """ return _number_to_X(number, uncertainty, unit, fmt, html_of_unit, _html_pow_10)