开发者

Python float copy question

开发者 https://www.devze.com 2022-12-25 05:37 出处:网络
I\'m puzzled by some behaviour I\'m seeing when copying a float array member into another variable - please help!

I'm puzzled by some behaviour I'm seeing when copying a float array member into another variable - please help!

For example

data_entry[1] = 9.开发者_C百科6850069951

new_value = data_entry[1]


<comment> #print both

9.6850069951


9.6850663300

I'm aware of the problem of binary storage of floats but I thought with a direct copy of memory we would end up with the same value.

Any ideas? I need better precision than this! thanks in advance Stuart


After an assignment the variable new_value is not a copy of the float, it's just another reference to the exact same object. Therefore it cannot possibly have a different printed representation. So there's definitely some detail omitted in the original question.

Stuart - can you please try the following and post the result, or tell us how your actual code varies. Note below that new_value is data_entry[1] i.e. they are both the same object.

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


If you're really using the array module (or numpy's arrays) the precision loss is easy to explain, e.g.:

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

here, the 'f' first arg to array.array says we're using 32-bit floats, so only about 7 significant digits "survive". But it's easy to use 64-bit floats (once upon a time those were known as "double precision"!-):

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

As you see, this way more than a dozen significant digits "survive" (you can typically rely on about 14+, unless you do arithmetic "oops"s such as taking the difference of numbers very close to each other, which of course devours your precision;-).


Didn't work for me with Python 2.6.2 on 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

One option would be to switch to using Decimal objects:

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

If you're losing precision somehow this might help.


You've left some code out.

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

The repr and the str of this floating-point number are producing different results. My guess is that the code you posted omitted mentioning this difference.


Here's some edited code formatted:

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
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号