Python:将float元素追加到数组会改变其精度,例如: 1.2至1.200000002

时间:2016-01-24 15:04:21

标签: python rounding-error

我遇到了一个非常奇怪的问题。我正在尝试创建一个函数,该函数返回一个值数组,这些值包含具有特定步长的范围(例如您可能在绘图的轴上找到)。而不仅仅是使用np.arange(min,max,step),我想要更好地围绕步长的东西。这是我试过的:

def get_decade(value):
    return pow(10,math.floor(math.log10(value)))

def get_steparray(min,max,delta):
    delta_step = float(get_decade(delta))
    next = math.floor(min/delta_step)*delta_step
    print next
    array = [next]
    while next < max:
        next = int((next+delta_step)/delta_step)*delta_step
        print next
        array.append(next)
        print array
    print array
    return array

打印声明在那里帮助我弄清楚发生了什么。这是我尝试运行它:

print get_steparray(1.032,1.431,0.1)

由此,我期待数组最终为[1.0,1.1,1.2,1.3,1.4,1.5]

以下是我从函数中获得的内容:

1.0
1.1
[1.0, 1.1]
1.2
[1.0, 1.1, 1.2000000000000002]
1.3
[1.0, 1.1, 1.2000000000000002, 1.3]
1.4
[1.0, 1.1, 1.2000000000000002, 1.3, 1.4000000000000001]
1.5
[1.0, 1.1, 1.2000000000000002, 1.3, 1.4000000000000001, 1.5]
[1.0, 1.1, 1.2000000000000002, 1.3, 1.4000000000000001, 1.5]

正如您所看到的,其中一些有效,而另一些则添加了额外的小数。

任何人都有任何想法可能导致这个?感谢您提供的任何见解。或者,如果有人知道创建这样一个数组的更好,更实用的方法,我会很高兴。也许我应该坚持使用np.arange并调整最大/最小/步长值?

(是的,我知道我的代码并不是最干净的。上面的函数开始时更清晰,但我添加了一些不必要的功能,试图让它工作。)

编辑:虽然我感谢所有人的深刻见解,但我仍然不确定他们是否完全解决了我的问题。正如在打印输出中可见的那样,当作为孤立的浮动类型时,每个值都以足够的精度存储。但是当它们被添加到数组中时,它们才会改变精度。一般来说,我非常清楚浮点问题,但对浮点数和数组之间的具体差异感到好奇。我想知道数组是否可以将值存储在比单个值更低的位数中。

话虽如此,我认为在使用时更多地关注格式化的建议是我最终会做的。

谢谢!

1 个答案:

答案 0 :(得分:1)

为什么?

这是一个典型的浮点算术问题。

我将在此处发布Python documentation for floating-point arithmetic issues and limitations的摘录,但大多数语言都是如此:

  

浮点数在计算机硬件中表示为基数2   (二元)分数。例如,小数部分

0.125
     

的值为1/10 + 2/100 + 5/1000,二进制的方式相同   分数

0.001
     

的值为0/2 + 0/4 + 1/8。这两个部分相同   值,唯一真正的区别是第一个写入   基数为10的分数表示法,第二个为基数2。

     

不幸的是,大多数小数部分不能完全表示为   二进制分数。结果是,一般来说,十进制   您输入的浮点数仅由二进制近似   实际存储在机器中的浮点数。

     

这个问题最初在基地10中更容易理解。考虑一下   分数1/3。您可以将其近似为基数10分数:

0.3
     

或者更好,

0.33
     

或者更好,

0.333
     

等等。无论你愿意记下多少位数,都可以   结果永远不会完全1/3,但会越来越好   近似1/3

<小时/>

如何?

现在你知道了为什么,这里 你可以解决这个问题。

如果您不需要所有这些精确度(或者就此而言......所有这些不精确),您可以随时:

  • 使用round内置
  • 保持数字不变,但只在需要为GUI或控制台打印时格式化