2010-03-26 62 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