2010-03-26 4 views
0

플로트 배열 구성원을 다른 변수로 복사 할 때 나타나는 몇 가지 동작에 당황합니다. 다른 변수 - 도와주세요!Python float copy 질문

예를

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 –

+3

여기에서 문제를 재현 할 수 없습니다. 두 값은 정확히 동일하게 인쇄됩니다 (소수점 이하 10 개 값). 파이썬 2.6 사용하고 있습니다.4 Windows XP에서 (해당 OS를 사용하는 것을 좋아하지는 않음) – Morlock

+0

이 문제를 재현 할 수있는 완전한 프로그램을 게시 할 수 있습니까? (단순한 할당으로 값이 바뀌지 않는다는 가정하에 실제로는 정확히 같은 'float' 객체가됩니다.) –

답변

0

리눅스에서 파이썬 2.6.2와 나를 위해 작동하지 않았다 :

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

경우 :

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

하나의 옵션은 사용 진수 객체로 전환하는 것 당신은 정밀도를 잃어 가고 있습니다. 어떻게 든 도움이 될 것입니다.

+0

@samtregar 'decimal'모듈을 사용하면 메모리 사용에 어떤 영향을 줍니까? (매우 큰 목록이나 배열을 사용한다고 생각할 때?) – Morlock

+2

@Morlock,'decimal.Decimal'을 사용하면 더 많은 메모리가 필요하고'float'을 사용하는 것보다 훨씬 느립니다. '플로트 (float)'가 (물리적 측정과 같은 것을 나타내는) 문제의 클래스에서 거의 항상 올바른 선택입니다. 'decimal.Decimal'의 주요 용도는 정확한 정밀도와 반올림 규칙으로 돈을 표현하고 돈을 포함하는 계산을 수행하는 것입니다. 'float'와 마찬가지로 표현과 반올림 오류가 있지만 정밀도는 매우 높게 수정할 수 있습니다. 후자가 충분히 정확하지 않았기 때문에'float'보다'Decimal'이 선택된 실제 소프트웨어를 아직 보지 못했습니다. –

+0

@samtregar 고맙습니다. 매우 명확합니다. – Morlock

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

당신이 정말로 정밀도 손실이 예를 들어, 설명 (배열 또는 numpy의) 쉽게되어 array 모듈을 사용하는 경우 : 여기

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

, array.array'f' 첫 번째 인수는 우리를 말한다 32 비트 부동 소수점을 사용하므로 약 7 자리 숫자 만 "생존"합니다. (! "배정 밀도"로 알려져 그 옛날 옛적에 -)하지만 64 비트 수레를 사용하기 쉽습니다 :

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

보시다시피, 다스보다는이 방법이 더 유효 숫자는 (당신을 "생존" 당신이 산술적 인 "oops"를하지 않는 한, 보통 서로의 수의 차를 취하는 것과 같지 않은 한, 대략 14++에 의존 할 수 있습니다.

+0

귀하의 의견과 조언에 감사드립니다. 알렉스의 제안을 사용하여 array.array ('d', x) 표현식을 사용하여 문제를 해결 한 것 같아서 원래 float 배열 에 충분한 정밀도가없는 것처럼 보입니다. 다음 코드에 더 많은 코드를 게시 할 예정입니다. 여기에 공백이 없기 때문입니다. – SJA

+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') if (data [index]! = 0) : test_data = data [인덱스] modlog (logging.INFO, '원시 데이터 = % .12f', 데이터 [(인덱스)] modlog (로깅 .INFO, 'test_data = % .12f', test_data) 출력 : : 정보 : 원시 데이터 = 2.333840588874 : 정보 : test_data = 2.333840588874 – SJA

+0

@SJA, 주석의 코드는 완전히 읽을 수 없습니다. 문제의 코드를 추가하려면 질문을 수정하십시오. 코드로 올바르게 형식을 지정할 수 있습니다. –

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