21

Pythonを使用して数値をエンジニアリング形式に印刷しようとしていますが、機能しないようです。構文SEEMSは十分に単純ですが、機能しません。

>>> import decimal 
>>> x = decimal.Decimal(1000000)
>>> print x
1000000
>>>> print x.to_eng_string() 
1000000

これがなぜなのか理解できません。2つの値は等しくありません(1つは文字列、もう1つはintです)。にさまざまなコンテキストを設定decimalすることも役に立たないようです。手がかりやアイデアはありますか?

4

7 に答える 7

25

これを機能させるには、最初に小数を正規化する必要があります。

>>> x = decimal.Decimal ('10000000')

>>> x.normalize()
Decimal('1E+7')

>>> x.normalize().to_eng_string()
'10E+6'

この理由は、ソース コードを掘り下げることによって発見できます。

to_eng_string()Python 2.7.3 ソース ツリー ( Lib/decimal.pygzip 圧縮されたソース tar ボールhere から)を調べると、単純に true__str__に設定して呼び出します。eng

次に、最初に小数点以下の桁数を決定することがわかります。

leftdigits = self._exp + len(self._int)

次の表は、これら 2 つの値の値を示しています。

                         ._exp       ._int         len   leftdigits
                         -----       ---------     ---   ----------
Decimal (1000000)            0       '1000000'       7            7
Decimal ('1E+6')             6       '1'             1            7

その後に続くコードは次のとおりです。

if self._exp <= 0 and leftdigits > -6:
    # no exponent required
    dotplace = leftdigits
elif not eng:
    # usual scientific notation: 1 digit on left of the point
    dotplace = 1
elif self._int == '0':
    # engineering notation, zero
    dotplace = (leftdigits + 1) % 3 - 1
else:
    # engineering notation, nonzero
    dotplace = (leftdigits - 1) % 3 + 1

また、特定の範囲 ( ) に指数が含まれself._exp > 0 or leftdigits <= -6いない限り、文字列表現では何も与えられないことがわかります。


さらなる調査により、この動作の理由が示されます。General Decimal Arithmetic Specificationコード自体を見ると、 (PDFはこちら)に基づいていることがわかります。

そのドキュメントを検索するとto-scientific-string(これto-engineering-stringに大きく基づいています)、一部を述べています(言い換え、太字で):

「to-scientific-string」操作は、指数が必要な場合は科学表記法を使用して数値を文字列に変換します。操作はコンテキストの影響を受けません。

数が有限数の場合:

係数は、最初に 0 から 9 までの文字を使用して 10 進数の文字列に変換されます (値がゼロの場合は例外で、その場合は単一の 0 文字が使用されます)。

次に、調整された指数が計算されます。これは、指数に、変換された係数の文字数を足して 1 を引いたものです。つまり、指数 + (clength-1) であり、clength は係数の長さ (10 進数) です。

指数が 0 以下で、調整後の指数が -6 以上の場合、数値は指数表記を使用せずに文字形式に変換されます。この場合、指数がゼロの場合、小数点は追加されません。それ以外の場合 (指数は負になります)、小数点の右側に文字数を指定する指数の絶対値と共に小数点が挿入されます。必要に応じて、変換後の係数の左側に「0」の文字が追加されます。この挿入後に小数点の前に文字がない場合は、従来の「0」文字が前に付けられます。

言い換えれば、それは標準がそうするように指示しているので、それがしていることをしている.

于 2012-09-07T03:16:10.817 に答える
4

自分でロールバックする必要があるように思えます:

from math import log10
def eng_str(x):
    y = abs(x)
    exponent = int(log10(y))
    engr_exponent = exponent - exponent%3
    z = y/10**engr_exponent
    sign = '-' if x < 0 else ''
    return sign+str(z)+'e'+str(engr_exponent)

部分のフォーマットにもう少し注意したいかもしれませんがz...

十分にテストされていません。バグを見つけたら自由に編集してください

于 2012-09-07T03:12:12.347 に答える
1

QuantiPhyは、これに役立つ別のパッケージです。QuantiPhyは、値と単位を 1 つのオブジェクトに結合するために使用されるQuantityクラスを提供します。さまざまな方法で数量をフォーマットできます。一般的には SI スケール ファクタが使用されますが、エンジニアリング形式もサポートされています。インストール:

pip3 install quantiphy

数値または文字列から始まるQuantityオブジェクトを作成できます。

>>> from quantiphy import Quantity
>>> q = Quantity(10000000)
>>> q.render(form='eng')
'10e6'

デフォルトでは、 QuantiPhyは SI 表記を使用しますが、デフォルトの形式を「eng」に設定できます。

>>> print(q)
10M
>>> Quantity.set_prefs(form='eng')
>>> print(q)
10e6

通常、単位を数量に指定します。

>>> f = Quantity(10_000_000, 'Hz')
>>> print(f)
10e6 Hz

Quantityはfloatのサブクラスであるため、float を使用する場所であればどこでも数量を使用できます。

QuantiPhyは、十分にサポートされ、十分に文書化されている強力なパッケージです。ぜひお試しください。

于 2020-12-03T03:08:03.633 に答える
1

matplotlib も使用できます。

>>> from matplotlib.ticker import EngFormatter
>>> engFormat = EngFormatter()
>>> print(engFormat(1000))
1 k

詳細とオプションについては、https://matplotlib.org/stable/api/ticker_api.htmlを参照してください。 別のより複雑な例:

>>> from matplotlib.ticker import EngFormatter
>>> engFormat = EngFormatter(unit='Hz',places=2,sep='')
>>> print(engFormat(1000))
1.00kHz
于 2021-04-21T15:46:29.607 に答える