2010-03-26 52 views
0

我對將浮動數組成員複製到 另一個變量時看到的一些行爲感到困惑 - 請幫助!Python浮動複製問題

例如

data_entry[1] = 9.6850069951 

new_value = data_entry[1] 


<comment> #print both 

9.6850069951 


9.6850663300 

我知道花車的二進制存儲的問題,但我認爲 的內存直接複製我們最終會得到相同的值。

任何想法?我需要比這更好的精確度! 由於事先 斯圖爾特

+0

對我來說,價值是相同的。 Mac OS X,Python 2.6.1 – 2010-03-26 16:43:33

+3

這裏無法重現問題。兩個值的打印完全相同(小數點後10個值)。我正在使用Python 2.6。4在Windows XP(不是我喜歡使用該操作系統) – Morlock 2010-03-26 16:46:24

+0

你能發佈一個完整的程序,我們可以運行,再現這個問題? (你的假設只是賦值不會改變這個值是正確的,事實上,它會讓它們成爲同一個確切的'float'對象。) – 2010-03-26 17:12:38

回答

0

並沒有爲我與Python 2.6.2 Linux上工作:

>>> data_entry = [1, 2] 
>>> data_entry[1] = 9.6850069951 
>>> new_value = data_entry[1] 
>>> print data_entry[1] 
--> print(data_entry[1]) 
9.6850069951 
>>> print new_value 
--> print(new_value) 
9.6850069951 

一個辦法是轉而使用十進制對象:

>>> from decimal import Decimal 
>>> data_entry[1] = Decimal('9.6850069951') 
>>> new_value = data_entry[1] 
>>> print data_entry[1] 
--> print(data_entry[1]) 
9.6850069951 
>>> print new_value 
--> print(new_value) 
9.6850069951 

如果不知怎的,你可能會失去精確度。

+0

@samtregar如何使用'十進制'模塊影響內存使用? (考慮到我使用非常大的列表或數組?) – Morlock 2010-03-26 16:50:46

+2

@Morlock,使用'decimal.Decimal'的內存密集程度更高,比使用'float'慢得多。對於「float」這一類問題(代表物理測量等事物)而言,它幾乎總是正確的選擇。 'decimal.Decimal'的主要用途是用正確的精確度和舍入規則來表示貨幣和執行涉及貨幣的計算。像'float'一樣,它具有表示和舍入錯誤,但精度可以修改得非常高。我還沒有看到真正的軟件,'十進制'選擇'浮動',因爲後者不夠精確。 – 2010-03-26 16:59:29

+0

@samtregar謝謝,非常清楚。 – Morlock 2010-03-26 17:18:03

0

您已經遺漏了一些代碼。

>>> data_entry=[0,0] 
>>> data_entry[1] = 9.6850069951 
>>> 
>>> new_value = data_entry[1] 
>>> print data_entry 
[0, 9.6850069951000002] 
>>> print new_value 
9.6850069951 
>>> print data_entry[1] 
9.6850069951 

repr的和這個浮點數的str正在產生不同的結果。我的猜測是你發佈的代碼中提到了這個區別。

4

賦值後,變量new_value不是float的副本,它只是對完全相同的對象的另一個引用。因此它不可能有不同的印刷表示。所以在原始問題中肯定會有一些細節。

斯圖爾特 - 你可以請嘗試以下併發布結果,或告訴我們你的實際代碼如何變化。請注意,new_value data_entry [1],即它們都是同一個對象。

>> data_entry = [0,0] 
>> data_entry[1] = 9.6850069951 
>> new_value = data_entry[1] 
>> new_value is data_entry[1] 
True 
>> print data_entry[1], new_value 
9.6850069951 9.6850069951 
3

如果你真的使用array模塊(或numpy的陣列)的精度損失很容易解釋,如:

>>> dataentry = array.array('f', [9.6850069951]) 
>>> dataentry[0] 
9.6850070953369141 

這裏,'f'第一個參數來array.array說,我們'使用32位浮點數,所以只有7位有效數字「存活」。但它易於使用的64位浮點(很久以前那些被稱爲「雙精度」一次 - !):

>>> dataentry = array.array('d', [9.6850069951]) 
>>> dataentry[0] 
9.6850069951000002 

正如你看到的,這樣十幾顯著數字「生存」(你通常可以依賴大約14+,除非你做算術「哎呀」,比如把數字的差別非常接近,這當然會吞噬你的精度;-)。

+0

感謝大家的意見和建議。使用亞歷克斯的建議,我似乎已經通過使用array.array('d',x)表達式來解決問題,所以看起來原始浮點數組 沒有足夠的精度。我會在 下一條評論中發佈更多代碼,因爲這裏沒有空間。 – SJA 2010-04-08 09:29:10

+0

old_code: 數據= [] 用於data_entry在數據: 如果(data_entry [1]!= 0): 值= data_entry [1] modlog(logging.INFO, '原始值=%.12f',data_entry [1]) modlog(logging.INFO, 'value_in =%.12f',值) 輸出: :INFO:原始值= 2.334650748292 :INFO:value_in = 2.334685585881 新的代碼: 數據= array.array( 'd') 如果(數據[索引] = 0): TEST_DATA =數據[索引] modlog(logging.INFO, '原始數據=%.12f',數據[(索引)]) modlog(記錄.INFO,'test_data =%.12f',test_data) 輸出: :INFO:raw data = 2.333840588874 :INFO:test_data = 2.333840588874 – SJA 2010-04-08 09:32:44

+0

@SJA,註釋中的代碼是完全不可讀的。請修改您的問題,以添加有問題的代碼,以便它可以正確格式化爲代碼。 – 2010-04-08 14:21:44

0

下面是一些格式化代碼編輯:

old code: 
data = [] 
for data_entry in data: 
    if (data_entry[1] != 0): 
    value = data_entry[1] 
    modlog(logging.INFO,'raw value = %.12f',data_entry[1]) 
    modlog(logging.INFO,'value_in = %.12f', value) 
output: 
:INFO:raw value = 2.334650748292 
:INFO:value_in = 2.334685585881 

new code: 
data = array.array('d') 
if (data[index] != 0): 
    test_data = data[index] 
    modlog(logging.INFO,'raw data = %.12f', data[(index)]) 
    modlog(logging.INFO,'test_data = %.12f', test_data) 
output: 
:INFO:raw data = 2.333840588874 
:INFO:test_data= 2.333840588874