繁体   English   中英

Python:让美元变得有意义

[英]Python: Making Dollars make Sense

当在程序中处理美元数字以在股票市场中进行自动交易(俗称“算法交易”)时,数字很难管理。 我认为这不是重复的,因为我还没有在其他类似的问题/答案中找到合适的解决方案。

如果我一个人运行[更新,原来是家里的2.7.2版本]

price_list = [1.0, 2.0, 2.5, 3.0, 4.0, 4.5, 4.6, 4.6, 4.7]
print price_list

...它打印出您在上面看到的方式。 但是在我的数千行程序中,Python似乎在说,您并不是真的意思,您真正的意思是:

>nasdaq_crunching_4d.py
[1.0, 2.0, 2.5, 3.0, 4.0, 4.5, 4.5999999999999996, 4.5999999999999996, 4.7000000000000002]

[更新:与我的程序中的两行代码没有任何关系。 多余的数字输出在我使用的远程主机上,Bluehost的版本为2.6.6。 我很惊讶有人使用2.6,看起来CentOS附带了2.6,并且他们提供了每用户升级的说明,很好。 但是,其余的问题仍然有效。 ]

...然后在不知不觉中,您就想把头缠在庞大的清单上(小开胃菜,我认为太辣了):

'slopes': [-40.280000000000001, 79.689999999999998, -40.56000000000... 
80.340000000000003, -40.420000000000002, 80.159999999999997, -40.28...
79.849999999999994, -40.090000000000003, 79.439999999999998, -39.96... 
79.129999999999995, -40.350000000000001, 79.829999999999998, -40.39...
80.030000000000001, -40.729999999999997, 80.719999999999999, -40.93... 

我想告诉Python,不,我的意思不是4.5999999999999996 ,我的意思是准确的4.60 ,如果需要的话,其次是十亿和一个零。我只想要这些数字中的两个,这样您就可以忽略其余的零。 但是,如果它是4.60 ,请顺便给我显示4.60 ,而不是4.6 ,绝对不是4.5999999999999996

这也不是好吃的:

'lst': [Decimal('124.75'), Decimal('125.18'), Decimal('125.18...
'ma_b': {'max': 4, 'now': Decimal('125.36'), 'lth': 5, 'slp':...
Decimal('125.18'), Decimal('125.25'), Decimal('125.36')]}, 'm...
0.06], 'lst': [Decimal('125.19'), Decimal('125.17' '118.19'),...

您可能想知道我正在导入数学(以使用数学中的各种函数),并且尝试过round(),float(),“%。2f”以及也许我现在忘记的其他函数。 有一个庞大而复杂的字典,其中包含股票代码,价格,移动平均线,斜率以及许多其他浮动货币,字符串和其他字典等各种列表。

有什么方法可以使美元始终如一地只是美元和美分呢? 谢谢。

您保持打印列表,并且列表使用repr()表示其内容。 如果您想进一步控制格式设置 ,则必须使用正确的格式设置:

print '[{}]'.format(', '.join([format(n, '.2f') for n in numbers_list]))

会将您的输出格式化为类似列表的字符串,所有浮点数都用小数点后的两位数字打印:

>>> numbers_list = [1.0, 2.0, 2.5, 3.0, 4.0, 4.5, 4.5999999999999996, 4.5999999999999996, 4.7000000000000002]
>>> print '[{}]'.format(', '.join([format(n, '.2f') for n in numbers_list]))
[1.00, 2.00, 2.50, 3.00, 4.00, 4.50, 4.60, 4.60, 4.70]

也许浮点数不是美元和美分值的最佳表示; 而是仅将美分存储为整数(4美元20美分变成420美分)。 毕竟,对于大多数目的而言,美分是不可分割的。

您正在使用浮点算法并期望精度。 无论使用哪种语言,这几乎都是行不通的。

使用整数表示固定的一美分(因此,不是4.60,而是一分钱的460000000百万分之一)。

您将无法轻松实现准确性和可变的小数位数

如果将其存储为小数:

annoying_list=[decimal.Decimal(3.42), decimal.Decimal(2.56)]
for  i in annoying_list: print float(i)

返回:

3.42

2.56

一种快速而肮脏的方法是在主模块的开头重新定义Decimal本身:

from decimal import Decimal

Decimal.__repr__ = lambda self: "{0:.2f}".format(self)

这将适用于所有小数,包括在外部模块中创建的所有小数。

另一种方法是创建自己的Decimal子类,但为了简单方便而定义新类型是一种不好的习惯,我认为:如果任何外部函数返回基本类型的对象,则需要将其转换为您所需要类型的新对象,它的效率是不必要的。 另外, Decimal使用插槽,并且是不可变的类型,因此任何子类都需要考虑这一点以保持效率。

更好的方法是定义自己的功能,以所需的方式显示它。 这样,您可以将重新格式化限制为仅在要使用它时使用。 但是,此功能将需要重新实现递归列表输出算法。 幸运的是,有一个repr库大大简化了这一过程。 这允许您定义每种类型的自定义repr实现,并内置支持列表和字典等递归对象:

from decimal import Decimal
from repr import Repr

class CustomRepr(Repr):
    def repr_Decimal(self, obj, level):
        return "{0:.2f}".format(obj)

cr = CustomRepr()

data = {"money": [Decimal("42")]}

print cr.repr(data)

输出:

{'money': [42.00]}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM