これを機能させるには、最初に小数を正規化する必要があります。
>>> 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.py
gzip 圧縮されたソース 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」文字が前に付けられます。
言い換えれば、それは標準がそうするように指示しているので、それがしていることをしている.