除了标准的数字属性,十进制浮点Decimal对象还有许多内置的方法。
adjusted() 返回科学记数法中的指数,用于确定最高有效位相对于小数点的位置。例如,用科学记数法写数字Decimal('321e+5')和Decimal('321e-5')分别是3.21×10^7和3.21×10^-3,所以Decimal('321e+5').adjusted() 返回 7 ,Decimal('321e-5').adjusted() 返回 -3。
as_integer_ratio() 返回一整数对 (n, d) ,把Decimal对象精确转换为带正分母的最简分数。对于Infinity抛出OverflowError,而NaN是ValueError。
as_tuple() 返回named tuple(具名元组,即元组的每个元素都有名字。) 表示Decimal对象:DecimalTuple(sign, digits, exponent)——(符号,有效数字元组,指数)。
canonical() 返回Decimal对象的规范编码。目前,一个Decimal对象的编码始终是规范的(输入不规范时,在输入过程中已经消除。),因此该操作返回与直接打印相同。
compare(other, context=None) 比较两个Decimal对象的值。compare()返回一个Decimal对象,如果任一操作数是NaN,那么结果是NaN;如果任一操作是sNaN(显式NaN),那么抛出异常InvalidOperation。context参数似乎没有什么作用,因为它只对运算结果进行有效数字舍入。
compare_signal(other, context=None) 与compare(other, context=None)基本一样,不过对于有一个参数是NaN的情况不是返回Decimal('NaN'),而是抛出信号,如果设置了相应的陷阱,就会抛出异常InvalidOperation。
compare_total(other, context=None)
使用两个操作数的抽象表示(可以认为是DecimalTuple)而不是它们的数值来比较。类似于compare()方法,不过是对全部项目的综合排序而得到结果(Decimal对象)。两个具有相同的数值但有效数字个数不同的Decimal对象比较,结果不相等。例如:
>>> Decimal('12.0').compare_total(Decimal('12'))
Decimal('-1')
下面是不考虑NaN和Infinity的算法(文本代码附录1)和运行结果:
静默NaN(NaN)和显式NaN(sNaN)也可以排序:。可见它们的排序是NaN>sNaN>数字或±Infinity。 如果两个操作数综合排序相同返回 Decimal('0');如果第一个操作数的综合排序低于第二个操作返回Decimal('-1');如果第一个操作数在综合排序高于第二个操作数返回Decimal('1')。 这个方法不受上下文影响且静默:不更改任何标志且不执行舍入。不过,如果底层的C语言程序无法准确转换第二个操作数,可能会引发InvalidOperation异常。
compare_total_mag(other, context=None) 这个方法与compare_total()相似,但忽略每个操作数的符号(即只比较绝对值)。x.compare_total_mag(y) 相当于 x.copy_abs().compare_total(y.copy_abs())。 这个方法不受上下文影响且静默:不更改任何标志且不执行舍入。不过,如果底层的C语言程序无法准确转换第二个操作数,可能会引发InvalidOperation异常。
conjugate() 只返回对象本身,这种方法只适用于规范的Decimal对象。
copy_abs() 返回对象的绝对值。这个方法不受上下文影响且静默:不更改任何标志且不执行舍入。
copy_negate() 返回对象的取反值。这个方法不受上下文影响且静默:不更改任何标志且不执行舍入。
copy_sign(other, context=None) 返回第一个操作数的副本,并把它的符号设置为第二个操作数的符号。 这个方法不受上下文影响且静默:不更改任何标志且不执行舍入。不过,如果底层的C语言程序无法准确转换第二个操作数,可能会引发InvalidOperation异常。
exp(context=None) 返回该数字的(自然)指数函数“e**x”的值。结果使用 ROUND_HALF_EVEN 舍入模式舍入。
classmethod from_float(f) 另一个构造函数,只接受float或int的参数。调用classmethod(类方法)时使用类名而不是对象名称。由于现在构造函数已支持float和int,所以这个类函数就不太必要了。 注:Decimal.from_float(0.1)与Decimal('0.1')不同,因为浮点数0.1不能准确用二进制浮点数表示,在计算机中储存的是它的最接近值。这个值用精确数表示是: 0.1000000000000000055511151231257827021181583404541015625。
fma(other, third, context=None) 混合乘法与加法。返回 self*other+third 值,中间乘积 self*other 没有舍入。
is_canonical() 如果参数是规范的,则为返回 True,否则为 False 。目前,Decimal实例总是规范的,所以这个操作总是返回 True 。
is_finite() 如果参数是一个有限的数,则返回为 True ;如果参数为无穷大或 NaN ,则返回为 False。
is_infinite() 如果参数为正负无穷大,则返回为 True ,否则为 False 。
is_nan() 如果参数为 NaN (无论是否静默),则返回为 True ,否则为 False 。
is_normal(context=None) 如果参数是一个标准的有限数则返回True。如果参数为零、次标准数(绝对值过小的数值,可能是不大于10^-9999999的数)、无穷大或NaN则返回False。
is_qnan() 如果参数为静默 NaN,返回 True,否则返回 False。
is_signed() 如果参数带有负号,则返回为True,否则返回False。注意,0和NaN都可带有符号。
is_snan() 如果参数为显式NaN,则返回True,否则返回 False。
is_subnormal(context=None) 如果参数为次标准数,则返回True,否则返回 False。
is_zero() 如果参数是0(正负皆可),则返回 True,否则返回 False。
ln(context=None) 返回操作数的自然对数(以 e 为底)。结果是使用 ROUND_HALF_EVEN 舍入模式舍入。
log10(context=None) 返回操作数的以十为底的对数。结果是使用 ROUND_HALF_EVEN 舍入模式舍入。
logb(context=None) 对于一个非零数(特别是浮点数),在做log10运算前调整生成一个与原十进制相符的副本,以这个副本做log10()运算得到一个Decimal实例的结果。与log10()一样,如果操作数是无限大则返回Decimal('Infinity') 。与log10()不同,如果操作数为零将抛出DivisionByZero异常。
logical_and(other, context=None) 按位“与”运算。两个操作数均为逻辑精确数(符号和指数都为0,系数是0和1组成的十进制数,下面三个方法的操作数也同样。)。
logical_invert(context=None) 按位“取反”运算。
logical_or(other, context=None) 按位“或”运算。
logical_xor(other, context=None) 按位“异或”运算。
max(other, context=None) 与内置函数max(self, other) 一样求两个数的最大值。该方法提供用户输入的Context舍入规则对返回结果进行舍入和用信号抛出规则(在上下文Context中讨论)。
max_mag(other, context=None) 与max()方法相似,不过是用操作数的绝对值进行比较的。
min(other, context=None) 与max()方法相似,求两个操作数的最小值。
min_mag(other, context=None) 与max_mag()方法相似,求两个操作数的最小值。
附录1:
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
#Decimal compare_total compare_total_mag 的算法from decimal import *def compareTotalMag(aDigits,aExponent,bDigits,bExponent): #compare_total_mag la, lb = len(aDigits), len(bDigits) #有效数字长度 sa = la + aExponent #科学记数法的指数+1 sb = lb + bExponent if sa > sb: #da绝对值较大 return Decimal('1') elif sa < sb: return Decimal('-1') num = min(la,lb) for i in range(num): if aDigits[i] > bDigits[i]: #对应数字大 return Decimal('1') elif aDigits[i] < bDigits[i]: #对应数字小 return Decimal('-1') if la == lb: #科学记数法指数和有效数字都相同 return Decimal('0') else: if la > lb: #a数有效数字较多 tmp = aDigits[lb:] op = True else: #b有效数字多 tmp = bDigits[la:] op = False if tmp.count(0) == abs(la-lb): #多出的有效数字全0 return Decimal('-1') if op else Decimal('1') else: return Decimal('1') if op else Decimal('-1') def compareTotal(da, db): #compare_total a,b = da.as_tuple(),db.as_tuple() #转变为具名元组 if a.sign > b.sign: #da为负,db为正 return Decimal('-1') elif a.sign < b.sign: return Decimal('1') elif a.sign > 0: #da,db为负 return -compareTotalMag(a.digits,a.exponent,b.digits,b.exponent) else: return compareTotalMag(a.digits,a.exponent,b.digits,b.exponent) if __name__ == "__main__": print("大小不同的两个同长正数比较 12.01 vs 12.11:") print(Decimal('12.01').compare_total(Decimal('12.11')), compareTotal(Decimal('12.01'),Decimal('12.11'))) print("大小不同的两个同长正数比较 12.11 vs 12.01:") print(Decimal('12.11').compare_total(Decimal('12.01')), compareTotal(Decimal('12.11'),Decimal('12.01'))) print("大小不同的两个不同长正数比较 12.1(短) vs 12.11(长):") print(Decimal('12.1').compare_total(Decimal('12.11')), compareTotal(Decimal('12.1'),Decimal('12.11'))) print("大小不同的两个不同长正数比较 12.11(长) vs 12.1(短):") print(Decimal('12.11').compare_total(Decimal('12.1')), compareTotal(Decimal('12.11'),Decimal('12.1'))) print("大小不同的两个同长负数比较 -12.01 vs -12.11:") print(Decimal('-12.01').compare_total(Decimal('-12.11')), compareTotal(Decimal('-12.01'),Decimal('-12.11'))) print("大小不同的两个同长负数比较 -12.11 vs -12.01:") print(Decimal('-12.11').compare_total(Decimal('-12.01')), compareTotal(Decimal('-12.11'),Decimal('-12.01'))) print("大小不同的两个不同长负数比较 -12.1(短) vs -12.11(长):") print(Decimal('-12.1').compare_total(Decimal('-12.11')), compareTotal(Decimal('-12.1'),Decimal('-12.11'))) print("大小不同的两个不同长负数比较 -12.11(长) vs -12.1(短):") print(Decimal('-12.11').compare_total(Decimal('-12.1')), compareTotal(Decimal('-12.11'),Decimal('-12.1'))) print("正数和负数比较 0.01 vs -0.01:") print(Decimal('0.01').compare_total(Decimal('-0.01')), compareTotal(Decimal('0.01'),Decimal('-0.01'))) print("负数和正数比较 -0.01 vs 0.01:") print(Decimal('-0.01').compare_total(Decimal('0.01')), compareTotal(Decimal('-0.01'),Decimal('0.01'))) print("正0和负0比较 +0.00 vs -0.00:") print(Decimal('+0.00').compare_total(Decimal('-0.00')), compareTotal(Decimal('+0.00'),Decimal('-0.00'))) print("负0和正0比较 -0.00 vs +0.00:") print(Decimal('-0.00').compare_total(Decimal('+0.00')), compareTotal(Decimal('-0.00'),Decimal('+0.00'))) print("正等值有效数字多与少比较 12.0 vs 12:") print(Decimal('12.0').compare_total(Decimal('12')), compareTotal(Decimal('12.0'),Decimal('12'))) print("正等值有效数字少与多比较 12 vs 12.0:") print(Decimal('12').compare_total(Decimal('12.0')), compareTotal(Decimal('12'),Decimal('12.0'))) print("负等值有效数字多与少比较 -12.0 vs -12:") print(Decimal('-12.0').compare_total(Decimal('-12')), compareTotal(Decimal('-12.0'),Decimal('-12'))) print("负等值有效数字少与多比较 -12 vs -12.0:") print(Decimal('-12').compare_total(Decimal('-12.0')), compareTotal(Decimal('-12'),Decimal('-12.0')))