Numpy妨碍了int - >浮式铸造

时间:2015-02-04 21:37:54

标签: python numpy

提前道歉 - 我似乎有一个非常根本的误解,我无法理解。我有一个四向量类,包含ct变量和位置向量。我正在编写代码来执行x方向洛伦兹增​​强。我遇到的问题是,我在下面写的,ct返回一个正确的浮点值,但x没有。四处乱转,我发现tempx是一个浮点数,但是将tempx赋值给r [0]并不会使它成为一个浮点数,而是向下舍入到一个int。我之前发布了关于可变性和不变性的问题,我怀疑这是问题所在。如果是这样,我显然有比预期更深的误解。无论如何,我有几个问题;

1a)如果使用a = FourVector实例化a(ct = 5,r = [55,2。,3]),则键入(a._r [0])返回numpy.float64而不是numpy.int32。这里发生了什么?我希望a._r [1]只是一个浮点数,而是改变整个列表的类型?

1b)如何获得上述行为(整个列表为浮点数),而不必将变量实例化为浮点数?我阅读了文档并尝试了各种方法,比如使用astype(float),但我所做的一切似乎都将它保存为int。再一次,认为这是我遇到的可变/不可改变的问题。

2)我曾经想过,在tempx = ...行中,乘以1.0会将其转换为浮点数,因为看起来这是ct转换为浮点数的原因,但由于某种原因,它并没有这样做。吨。也许和其他原因一样?

import numpy as np

class FourVector():
    def __init__(self, ct=0, x=0, y=0, z=0, r=[]):
        self._ct = ct
        self._r = np.array(r)
        if r == []:
            self._r = np.array([x,y,z])

    def boost(self, beta):
        gamma=1/np.sqrt(1-(beta ** 2))
        tempct=(self._ct*gamma-beta*gamma*self._r[0])
        tempx=(-1.0*self._ct*beta*gamma+self._r[0]*gamma)
        self._ct=tempct
        print(type(self._r[0]))
        self._r[0]=tempx.astype(float)
        print(type(self._r[0]))

a = FourVector(ct=5,r=[55,2,3])
b = FourVector(ct=1,r=[4,5,6])
print(a._r)
a.boost(.5)
print(a._r)

1 个答案:

答案 0 :(得分:10)

你所有的问题确实都是相关的。

numpy数组是一个有效保存对象的数组。它通过使这些对象具有相同的类型,如字符串(长度相等)或整数或浮点数来实现。然后,它可以很容易地计算每个元素需要多少空间以及它必须包含多少字节"跳跃"访问下一个元素(我们称之为" strides")。

当您从列表中创建数组时,numpy将尝试从该列表中确定合适的数据类型(" dtype"),以确保可以很好地表示所有元素。只有当您明确指定dtype时,才会进行有根据的猜测。

考虑以下示例:

>>> import numpy as np
>>> integer_array = np.array([1,2,3])  # pass in a list of integers
>>> integer_array
array([1, 2, 3])
>>> integer_array.dtype
dtype('int64')

如您所见,在我的系统上,它返回一个int64的数据类型,它是使用8个字节的整数表示。它选择了这个,因为:

  1. numpy识别列表中的所有元素都是整数
  2. 我的系统是64位系统
  3. 现在考虑尝试更改该数组:

    >>> integer_array[0] = 2.4  # attempt to put a float in an array with dtype int
    >>> integer_array # it is automatically converted to an int!
    array([2, 2, 3])
    

    如您所见,一旦设置了数组的数据类型,就会自动转换为该数据类型。 现在让我们考虑当你传入一个至少有一个浮点数的列表时会发生什么:

    >>> float_array = np.array([1., 2,3])
    >>> float_array
    array([ 1.,  2.,  3.])
    >>> float_array.dtype
    dtype('float64')
    

    numpy再一次确定了这个数组的合适数据类型。

    盲目地尝试更改数组的数据类型是不明智的:

    >>> integer_array.dtype = np.float32
    >>> integer_array
    array([  2.80259693e-45,   0.00000000e+00,   2.80259693e-45,
             0.00000000e+00,   4.20389539e-45,   0.00000000e+00], dtype=float32)
    

    你可能会说这些数字是胡言乱语。这是因为numpy试图将该数组的内存位置重新解释为4字节浮点数(技术人员将能够将数字转换为二进制表示,并从那里重新解释原始整数值)。

    如果你想演员,你必须明确地做,而numpy会返回一个 new 数组:

    >>> integer_array.dtype = np.int64 # go back to the previous interpretation
    >>> integer_array
    array([2, 2, 3])
    >>> integer_array.astype(np.float32)
    array([ 2.,  2.,  3.], dtype=float32)
    

    现在,要解决您的具体问题:

      

    1a)如果使用a = FourVector实例化a(ct = 5,r = [55,2。,3]),则键入(a._r [0])返回numpy.float64而不是numpy.int32。这里发生了什么?我希望a._r [1]只是一个浮点数,而是改变整个列表的类型?

    那是因为numpy必须确定整个数组的数据类型(除非你使用structured array),确保所有元素都适合该数据类型。只有这样,numpy才能有效地迭代该数组的元素。

      

    1b)如何获得上述行为(整个列表为浮点数),而不必将变量实例化为浮点数?我阅读了文档并尝试了各种方法,比如使用astype(float),但我所做的一切似乎都将它保存为int。再一次,认为这是我遇到的可变/不可改变的问题。

    创建阵列时指定dtype。在您的代码中,那将是:

    self._r = np.array(r, dtype=np.float)
    
      

    2)我曾经想过,在tempx = ...行中,乘以1.0会将其转换为浮点数,因为看起来这是ct转换为浮点数的原因,但由于某种原因,它并没有这样做。吨。也许和其他原因一样?

    这是事实。尝试打印tempx的数据类型,它应该是一个浮点数。但是,稍后,您将该值重新插入到数组self._r中,该数组的dtype为int。正如您之前看到的那样,它会将浮点数转换回整数类型。