如何在numpy中将负数舍入为零时消除额外减号?

Ara*_*D_B 12 python numpy unique rounding

我有一个关于fixfloor函数的简单问题numpy.当将大于-1的负数向零舍入时,将numpy它们正确地舍入为零但是留下负号.这个负号干扰了我的服装unique_rows函数,因为它使用ascontiguousarray比较数组的元素,这个符号扰乱了唯一性.圆形和修复在这方面表现相同.

>>> np.fix(-1e-6)
Out[1]: array(-0.0)
>>> np.round(-1e-6)
Out[2]: -0.0
Run Code Online (Sandbox Code Playgroud)

有关如何摆脱标志的任何见解?我考虑使用该np.sign功能,但它带来了额外的计算成本.

提前致谢.

tom*_*m10 9

你之间有问题-0.,并+0.为花车应该如何表现(IEEE754)规范的一部分.在某些情况下,人们需要这种区别.例如,请参阅文档中链接到的文档around.

值得注意的是,两个零应该相等,所以

np.array(-0.)==np.array(+0.) 
# True
Run Code Online (Sandbox Code Playgroud)

也就是说,我认为问题更可能与您的唯一性比较.例如:

a = np.array([-1., -0., 0., 1.])
np.unique(a)
#  array([-1., -0.,  1.])
Run Code Online (Sandbox Code Playgroud)

如果要将数字保持为浮点但所有零都相同,则可以使用:

x = np.linspace(-2, 2, 6)
#  array([-2. , -1.2, -0.4,  0.4,  1.2,  2. ])
y = x.round()
#  array([-2., -1., -0.,  0.,  1.,  2.])
y[y==0.] = 0.
#  array([-2., -1.,  0.,  0.,  1.,  2.])

# or  
y += 0.
#  array([-2., -1.,  0.,  0.,  1.,  2.])    
Run Code Online (Sandbox Code Playgroud)

但请注意,由于您试图避免浮点规范,因此必须执行此项额外工作.

另请注意,这不是由于舍入错误.例如,

np.fix(np.array(-.4)).tostring().encode('hex')
# '0000000000000080'
np.fix(np.array(-0.)).tostring().encode('hex')
# '0000000000000080'
Run Code Online (Sandbox Code Playgroud)

也就是说,结果数字完全相同,但是

np.fix(np.array(0.)).tostring().encode('hex')
# '0000000000000000'
Run Code Online (Sandbox Code Playgroud)

是不同的.这就是你的方法不起作用的原因,因为它正在比较数字的二进制表示,这对于两个零是不同的.因此,我认为问题更多的是比较方法,而不是比较浮点数的唯一性.

针对各种方法的快速测试:

data0 = np.fix(4*np.random.rand(1000000,)-2)
#   [ 1. -0.  1. -0. -0.  1.  1.  0. -0. -0. .... ]

N = 100
data = np.array(data0)
print timeit.timeit("data += 0.", setup="from __main__ import np, data", number=N)
#  0.171831846237
data = np.array(data0)
print timeit.timeit("data[data==0.] = 0.", setup="from __main__ import np, data", number=N)
#  0.83500289917
data = np.array(data0)
print timeit.timeit("data.astype(np.int).astype(np.float)", setup="from __main__ import np, data", number=N)
#  0.843791007996
Run Code Online (Sandbox Code Playgroud)

我同意@ senderle的观点,如果你想进行简单而精确的比较,并且可以通过整数来实现,那么整数通常会更容易.但是如果你想要独特的花车,你也应该能够做到这一点,尽管你需要更加小心.浮点数的主要问题是你可以有很小的差异可以从计算中引入并且不会出现在正常情况下print,但这不是一个巨大的障碍,特别是在round, fix, rint一个合理范围的浮点数之后.


sen*_*rle 5

我认为根本问题在于你对浮点数使用类似集合的操作 - 这是一般规则要避免的事情,除非你有充分的理由和对浮点数的深刻理解.

遵循此规则的显而易见的原因是,即使两个浮点数之间的非常小的差异也会记录为绝对差异,因此数值错误会导致类似集合的操作产生意外结果.现在,在您的用例中,最初看起来您可能通过先舍入来避免该问题,从而限制了可能值的范围.但事实证明,正如这个角落案例所示,仍然可能出现意想不到的结果.浮点数很难推理.

我认为正确的解决方法是圆形然后转换为int使用astype.

>>> a
array([-0.5,  2. ,  0.2, -3. , -0.2])
>>> numpy.fix(a)
array([-0.,  2.,  0., -3., -0.])
>>> numpy.fix(a).astype(int)    # could also use 'i8', etc...
array([ 0,  2,  0, -3,  0])
Run Code Online (Sandbox Code Playgroud)

由于您已经四舍五入,因此不应丢弃任何信息,并且以后对于类似集合的操作它将更加稳定和可预测.这是最好使用正确抽象的情况之一!

如果您需要花车,您可以随时转换回来.唯一的问题是它创建了另一个副本; 但大多数时候这不是一个真正的问题.numpy足够快,复制的开销非常小!

我要补充一点,如果你的案例真的要求使用花车,那么tom10的答案是好的.但我觉得真正需要浮动和固定操作的案例数量非常少.