-2

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

如果我单独运行这个[更新,原来这是家里的 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 一起提供的,而且他们为每个用户提供了升级说明,很好。然而,问题的其余部分仍然有效。]

...然后在不知不觉中,您正试图围绕庞大的清单(小开胃菜,在我看来太辣了):

'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”以及我现在忘记的其他方法。有一个大而复杂的字典,其中包含各种股票代码、价格、移动平均线、斜率和许多其他浮点数以及字符串和其他字典等列表。

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

4

4 回答 4

3

您保留打印列表,列表使用repr()代表它们的内容。如果您想对格式进行更多控制,则必须使用正确的格式:

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

会将您的输出格式化为类似列表的字符串,其中所有浮点数在小数点后以 2 位数字打印:

>>> 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 美分)。毕竟,在大多数情况下,美分是不可分割的。

于 2014-01-21T19:11:57.677 回答
2

您正在使用浮点运算并期望准确性。在任何语言中,这几乎都行不通。

使用整数来表示一美分的固定分数(所以不是 4.60,而是 460000000 百万分之一便士)。

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

于 2014-01-21T19:12:43.097 回答
2

如果将其存储为小数:

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

返回:

3.42

2.56

于 2014-01-21T19:13:39.073 回答
1

一种快速而肮脏的方法是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]}
于 2014-01-24T15:17:02.307 回答