我想知道我是否引起了问题,因为我在 Python2.7 中错误地将数据类型分配给和转换 numpy-array。
我正在做的是从 numpy.float64 类型将 hdf5 64 位整数值读取到 numpy.zeros() 数组!然后将这些值写入另一个分配 64 位无符号整数的 hdf5!
一些原始值的两个示例,这些值实际上是 ID 号(因此它们不会因数据类型转换而更改至关重要):
12028545243
12004994169
问题 1:第二个 hdf5 文件中的无符号整数是否与原始文件中相同?
我用一个小的子样本检查了这一点,但我无法控制是否适用于所有子样本(有数百万个)!
问题 2:如果我将 64 位值从原始文件读取到 数据类型=float64 的 numpy 数组,然后执行以下操作:
value=int(value)
value.astype(int64)
这是完全是原始值还是由于转换而改变?
问题 3:Python 会把我假设的值解释为 (a)、(b)、(c) 和 (d) 吗?格式化值也会有问题,比如使用科学记数法"e+10"?还是 Python 将它们识别为相同的值(因为它只是显示它们的不同方式......
1.20285452e+10 == 12028545243.0 == 12028545243 == 12028545243
1.20049942e+10 == 12004994169.0 == 12004994169 == 12004994169
(a) (b) (c) (d)
(a) 列出值打印一列名为 Data 的数组:
print data[:,0] <type 'numpy.ndarray'>
(b) 打印数据中的单个元素
print data[0,0] <type 'numpy.float64'>
(c) 进行转换后
print int(data[0,0]) <type int>
(d) 与 (a) 相同,但使用 astype() 进行转换!
print data[:,0].astype(numpy.int64) <type 'numpy.ndarray'>
您可能会问为什么为了安全起见,我不为 numpy 数组分配 int64 类型?是的,我会这样做,但是有些数据已经错误地存储了,我需要知道我是否仍然可以信任这些数据......
我正在使用: Python2.7, Pythonbrew, Ubuntu 14.04 LTS 64-bit on Lenovo T410
通常,不会保存将 64 位整数存储在 64 位浮点数中。例如,您可以通过查看以下内容轻松看到这一点:
import numpy as np
print(np.int64(2**63-1))
print(np.int64(np.float64(2**63-1))
虽然第一个会给你正确的结果 (9223372036854775807),但第二个有一个舍入误差,导致整数溢出 (-9223372036854775808)。
要理解这一点,您必须查看这些数字是如何存储的。虽然整数基本上只将其绝对值存储在二进制中(加上一个用于数字符号的位),但这不适用于浮点数。
浮点数将数字分为三部分存储。一个是符号位,下一个是有效/尾数,最后一个是指数。然后将该数字作为符号时间尾数乘以 2^指数给出。这三个必须共享可用的位(在您的案例中为 64)。正如 numpy 文档中为 anp.float64
指定的那样,52 位用于有效,11 位用于指数。因此,仅对于最多 52 位的整数,如果将它们转换为np.float64
并返回,您最终会得到正确的结果。
因此,要回答您的第一个和第二个问题:不,如果您的数据集中有任何大于2**52-1
的数字,则无法确定数字是否相同。
关于您的第三个问题:仅在打印值时进行格式化。在内部比较数字时,数字没有任何格式,因此只要所有这些值具有完全相同的值,它们就会被视为相等。
顺便说一句,如果你想了解更多关于浮点算术的知识,一个非常好的阅读是大卫戈德堡的论文"每个计算机科学家都应该知道的关于浮点算术"。
这取决于 Numpy 是将您的 int64 值转换为 float64,然后再转换回整数,还是仅将 int 数据存储在为 float64 保留的内存中。我假设第一个选项是正确的。 即使不检查 float64 interna(女巫无论如何都应该做)。很明显,float64 不能对所有2**64
不同的整数都有唯一的表示,如果它本身只有2**64
不同的代码并且还需要一些用于0.1
等等。Float64 使用 52 位来存储一个 53 位长的规范化尾数(最高有效位是隐式 1),所以如果你的 int 有非零位,那么它们在第一个之后多 52 位,就像:
5764607523034234887
= 0x5000000000000007
= 0b0101000000000000000000000000000000000000000000000000000000000111
(女巫是一个完美的64位整数)
最后,0b111
部分在转换为双倍后会被四舍五入并丢失,以便将数字放入尾数。然后,此信息将永远丢失。您的某些 ID 可能会发生这种情况,因为它们通常是相当大的数字。 因此,请尝试将数组调整为 int64。