简体   繁体   English

Python abs() function 在负数上失败

[英]Python abs() function failing on negative number

I'm working in python3.6 on linux and came across a pretty obvious failure of the abs() function.我在 linux 上的 python3.6 中工作,遇到了 abs() function 的一个非常明显的故障。 My variable x ended up as a very large negative number (possibly -inf ), but the absolute value abs() function still returned a negative number, which shouldn't be possible.我的变量x最终成为一个非常大的负数(可能是-inf ),但绝对值abs() function 仍然返回一个负数,这应该是不可能的。 I put in a quick fix for my code by just adding 0.1 to the input of abs() but.... am I misunderstanding how abs() should be used?我通过在abs()的输入中添加 0.1 来快速修复我的代码,但是....我误解了abs()应该如何使用?

$> x
-9223372036854775808

$> abs(x)
-9223372036854775808

$> np.abs(x)
-9223372036854775808

$> abs(x+.1)
9.223372036854776e+18

$> np.abs(x+.1)
9.223372036854776e+18

EDIT: Solved below, but it boils down to x being a numpy.int64 and not just int , unbeknownst to me.编辑:在下面解决,但归结为xnumpy.int64而不仅仅是int ,我不知道。

You didn't think to mention it (I inferred it from your tests with np.abs ), but it's important that x is a numpy.int64 (or equivalent signed 64 bit type).您没有想到要提及它(我从您使用np.abs的测试中推断出来),但重要的是xnumpy.int64 (或等效的有符号 64 位类型)。 That specific value, in two's complement , has no positive equivalent, so abs just produces the same value again (it could be made to raise an exception, but numpy stuck with the low level C behavior where it returns the original value in this case).该特定值在二进制补码中没有正等值,因此abs只会再次产生相同的值(可以引发异常,但numpy坚持低级别 C 行为,在这种情况下它返回原始值) .

Convert it to a true Python int first, eg abs(int(x)) and it will work.首先将其转换为真正的 Python int ,例如abs(int(x))并且它将起作用。


Explanation of why it works this way:解释为什么它以这种方式工作:

The bit pattern of -9223372036854775808 is 0x8000_0000_0000_0000 (highest bit only is set, underscores for readability). 0x8000_0000_0000_0000 -9223372036854775808仅设置了最高位,下划线是为了便于阅读)。 Two's complement negation is handled algorithmically by flipping all the bits and then adding one, with carry, so the conversion changes 0x8000_0000_0000_0000 to 0x7fff_ffff_ffff_ffff (all bits flipped), then adds 1 , which carries the whole length of the field (since every bit but the high bit is set), producing 0x8000_0000_0000_0000 again.二进制补码否定是通过翻转所有位然后加一个进位的算法处理的,因此转换将0x8000_0000_0000_0000更改为0x7fff_ffff_ffff_ffff (所有位都翻转),然后添加1 ,它携带字段的整个长度(因为除了高位被设置),再次产生0x8000_0000_0000_0000 That same bit pattern does actually correspond to the bit pattern an unsigned 64 bit quantity equal to 9223372036854775808 would have, but given it's interpreted as signed, it continues to be interpreted as the most negative value, not one higher than the most positive value int64 value (which can't be represented as an int64 ).相同的位模式实际上对应于等于9223372036854775808的无符号 64 位数量的位模式,但鉴于它被解释为有符号,它继续被解释为最负值,而不是比最正值int64值高一个(不能表示为int64 )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM