簡體   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