Python Decimal – технические обозначения для mili (10e-3) и микро (10e-6)

Вот пример, который беспокоит меня:

>>> x = decimal.Decimal('0.0001') >>> print x.normalize() >>> print x.normalize().to_eng_string() 0.0001 0.0001 

Есть ли способ иметь технические обозначения для представления mili (10e-3) и micro (10e-6)?

5 Solutions collect form web for “Python Decimal – технические обозначения для mili (10e-3) и микро (10e-6)”

Вот функция, которая делает вещи явно, а также поддерживает использование суффиксов СИ для экспоненты:

 def eng_string( x, format='%s', si=False): ''' Returns float/int value <x> formatted in a simplified engineering format - using an exponent that is a multiple of 3. format: printf-style string used to format the value before the exponent. si: if true, use SI suffix for exponent, eg k instead of e3, n instead of e-9 etc. Eg with format='%.2f': 1.23e-08 => 12.30e-9 123 => 123.00 1230.0 => 1.23e3 -1230000.0 => -1.23e6 and with si=True: 1230.0 => 1.23k -1230000.0 => -1.23M ''' sign = '' if x < 0: x = -x sign = '-' exp = int( math.floor( math.log10( x))) exp3 = exp - ( exp % 3) x3 = x / ( 10 ** exp3) if si and exp3 >= -24 and exp3 <= 24 and exp3 != 0: exp3_text = 'yzafpnum kMGTPEZY'[ ( exp3 - (-24)) / 3] elif exp3 == 0: exp3_text = '' else: exp3_text = 'e%s' % exp3 return ( '%s'+format+'%s') % ( sign, x3, exp3_text) 

decimal модуль выполняет десятичную арифметическую спецификацию , которая гласит:

to-science-string – преобразование в числовую строку

[…]

Коэффициент сначала преобразуется в строку в базе десять с использованием символов от 0 до 9 без начальных нулей (кроме случаев, когда его значение равно нулю, и в этом случае используется один символ 0). Затем вычисляется скорректированный показатель; это показатель, плюс число символов в преобразованном коэффициенте, меньше одного. То есть показатель экспоненты + (clength-1), где clength – это длина коэффициента в десятичных разрядах.

Если показатель меньше или равен нулю, а скорректированный показатель больше или равен -6, число будет преобразовано в символьную форму без использования экспоненциальной нотации.

[…]

to-engineering-string – преобразование в числовую строку

Эта операция преобразует число в строку, используя техническую нотацию, если требуется показатель степени.

Преобразование точно следует правилам преобразования в научную числовую строку, за исключением случаев конечных чисел, где используется экспоненциальная нотация.

Или, другими словами:

 >>> for n in (10 ** e for e in range(-1, -8, -1)): ... d = Decimal(str(n)) ... print d.to_eng_string() ... 0.1 0.01 0.001 0.0001 0.00001 0.000001 100E-9 

«Полная» цитата показывает, что не так!

decimal модуль действительно соответствует проприетарной (IBM) десятичной арифметической спецификации. Цитируя эту спецификацию IBM в decimal.to_eng_string() ясно показывает, что не так с decimal.to_eng_string() (выделено мной):

to-engineering-string – преобразование в числовую строку

Эта операция преобразует число в строку, используя техническую нотацию, если требуется показатель степени.

Преобразование точно следует правилам преобразования в научную числовую строку, за исключением случаев конечных чисел, где используется экспоненциальная нотация. В этом случае преобразованный экспонент корректируется как кратный трем (инженерная нотация) , позиционируя десятичную точку с одним, двумя или тремя символами, предшествующими ей (т. Е. Часть до десятичной точки будет варьироваться от 1 до 999 ). Это может потребовать добавления одного или двух завершающих нулей.

Если после корректировки десятичная точка не будет следовать цифре, она не будет добавлена. Если конечный показатель равен нулю, то никакая буква и показатель индикатора не будут суффиксными.

Эта проприетарная спецификация IBM фактически допускает не применять инженерную нотацию для чисел с бесконечным десятичным представлением , для которого вместо этого используется обычная научная нотация! Это явно неправильное поведение, для которого был открыт отчет об ошибке Python .

Решение

 from math import floor, log10 def powerise10(x): """ Returns x as a*10**b with 0 <= a < 10 """ if x == 0: return 0,0 Neg = x < 0 if Neg: x = -x a = 1.0 * x / 10**(floor(log10(x))) b = int(floor(log10(x))) if Neg: a = -a return a,b def eng(x): """Return a string representing x in an engineer friendly notation""" a,b = powerise10(x) if -3 < b < 3: return "%.4g" % x a = a * 10**(b % 3) b = b - b % 3 return "%.4gE%s" % (a,b) 

Источник: https://code.activestate.com/recipes/578238-engineering-notation/

Результат испытаний

 >>> eng(0.0001) 100E-6 

Основываясь на превосходном ответе Джулиана Смита (и на этом ответе), я изменил функцию, чтобы улучшить следующие моменты:

  • Совместимость с Python3 (целочисленное деление)
  • Совместимо для ввода 0
  • Округление до значительного числа цифр, по умолчанию 3, без конечных нулей, напечатанных

так что вот обновленная функция:

 import numpy as np def eng_string( x, sig_figs=3, si=True): """ Returns float/int value <x> formatted in a simplified engineering format - using an exponent that is a multiple of 3. sig_figs: number of significant figures si: if true, use SI suffix for exponent, eg k instead of e3, n instead of e-9 etc. """ x = np.float(x) sign = '' if x < 0: x = -x sign = '-' elif x == 0: exp = 0 exp3 = 0 x3 = 0 else: exp = int( np.floor( np.log10( x))) exp3 = exp - ( exp % 3) x3 = x / ( 10 ** exp3) x3 = round( x3, -int(np.floor(np.log10(abs( x3 ))) - (sig_figs-1)) ) if x3 == int(x3): # prevent from displaying .0 x3 = int(x3) if si and exp3 >= -24 and exp3 <= 24 and exp3 != 0: exp3_text = 'yzafpnum kMGTPEZY'[ exp3 // 3 + 8] elif exp3 == 0: exp3_text = '' else: exp3_text = 'e%s' % exp3 return ( '%s%s%s') % ( sign, x3, exp3_text) 

Я понимаю, что это старый поток, но он подходит к началу поиска python engineering notation для python engineering notation и кажется разумным, чтобы эта информация находилась здесь.

Я инженер, которому нравятся инженерные единицы «инженерная 101». Мне даже не нравятся обозначения, такие как 0.1uF , я хочу, чтобы это прочитало 100nF . Я играл с классом Decimal и не очень любил его поведение по диапазону возможных значений, поэтому я свернул пакет с именем engineering_notation который можно установить в pp-install.

 pip install engineering_notation 

Изнутри Python:

 >>> from engineering_notation import EngNumber >>> EngNumber('1000000') 1M >>> EngNumber(1000000) 1M >>> EngNumber(1000000.0) 1M >>> EngNumber('0.1u') 100n >>> EngNumber('1000m') 1 

Этот пакет также поддерживает сравнения и другие простые числовые операции.

https://github.com/slightlynybbled/engineering_notation

  • Как удалить последний utf8-символ строки python
  • Получение бесконечного цикла в серии фибоначчи в Python
  • Как распаковка кортежа отличается от обычного назначения?
  • Потоковое видео на GAE
  • ключевое слово в Python
  • Как установить текст по умолчанию для виджета Tkinter Entry
  • Получение ошибки «ImportError: невозможно импортировать имя HTTPSConnection» в Python 2.7
  • Я не могу установить 'pip' для python
  • Python - лучший язык программирования в мире.