1
\$\begingroup\$

Follow up of Pretty print with unit and physical suffix

My first code didn't process negative numbers correctly. Additionally I tried to use all of the helpful input to come up with this solution.

I considered:

  • precision
  • testing
  • spacing tips

P.S.: I use the 'u' instead of U+03BC because I had some difficulties displaying it on my Windows console.

# -*- coding: utf-8 -*-
import math
def eng_format(x, unit='', precision=3):
 UNITS = [' ', ' k', ' M', ' G'] + \
 ([None] * 10) + \
 [' f', ' p', ' n', ' u', ' m']
 power_of_1000 = int(math.floor(math.log10(abs(x)) // 3))
 exponent = 3 * power_of_1000
 prefix = UNITS[power_of_1000]
 if prefix is None:
 prefix = '*10^%d ' % exponent
 predecimal = 1+int(math.floor(math.log10(abs(x)) % 3))
 significand = x * 10**(-exponent + precision - predecimal)
 significand = round(significand) / 10**(precision - predecimal)
 postdecimal = precision - predecimal
 if(postdecimal < 0):
 postdecimal = 0
 FormatStr = '{:.%df}{:s}{:s}'%(postdecimal)
 return FormatStr.format(significand, prefix, unit)
if __name__ == '__main__':
 import unittest
 class TestPrettyPrinting(unittest.TestCase):
 def setUp(self):
 self.seq = list()
 self.seq.append( (0.002777, 'V', 3, '2.78 mV') )
 self.seq.append( (0.02777, 'V', 3, '27.8 mV') )
 self.seq.append( (0.2777, 'V', 3, '278 mV') )
 self.seq.append( (2.777, 'V', 3, '2.78 V') )
 self.seq.append( (27.77, 'V', 3, '27.8 V') )
 self.seq.append( (2./3, 'V', 6, '666.667 mV') )
 self.seq.append( (0.000003221, 'A', 3, '3.22 uA') )
 self.seq.append( (30589, 'A', 4, '30.59 kA') )
 self.seq.append( (60000000, 'W', 6, '60.0000 MW') )
 self.seq.append( (6000000000000000, 'W', 1, '6*10^15 W') )
 self.seq.append( (.0000000000000006, 'W', 4, '600.0*10^-18 W') )
 def test_eng_format(self):
 for value, unit, precission, expected_result in self.seq:
 for si, s in enumerate(['', '-']):
 new_expected_result = s + expected_result
 result = eng_format(value * (-1)**si, unit, precission)
 print "%20s %20s"%(result, new_expected_result)
 self.assertEqual(result, new_expected_result)
 unittest.main()
asked May 18, 2014 at 17:51
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

The computation of postdecimal can be simplified to postdecimal = max(precision - predecimal, 0).

eng_format needs a docstring.

On self.seq:

  • It needs a meaningful name like examples.
  • It should be local to test_eng_format, since that's the only place it's used.
  • It can be built in one expression, without mutation:

    examples = [(0.002777, 'V', 3, '2.78 mV'),
     (0.02777, 'V', 3, '27.8 mV'),
     ...]
    
  • However, looping over a list of test cases is less readable than a bunch of self.assertEqual(eng_format(-0.1, 'A', 6), '-100.000 mA') calls.

test_eng_format should not print all its test cases. Tests should be silent unless they fail.

answered May 18, 2014 at 19:42
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.