对于其他原语数字,如Math.signum(double)、int、或long,在Java中是否有对应的函数用于或。我不想写这样的代码
int sign = (int) Math.signum((double) intValue);
当有更好的选择的时候。
发布于 2017-01-18 10:41:18
发布于 2019-03-20 11:24:14
只是这方面的一些实施细节的增编:
public static int signum(int i) {
// HD, Section 2-7
return (i >> 31) | (-i >>> 31);
}
Integer::signum
说:如果数字是负数,我会给你-1
,如果数字是零,则给出0
,如果数字是正,则给出1
。例如,通过一些嵌套的if/else
,这是相当微不足道的。
相反,JDK使用的解决方案有点花哨。(x >> 31) | (-x >>> 31)
。看起来很容易,对吧?第一部分:x >> 31
是向右的有符号移位;它被称为签名,因为它在转换后保留符号。
假设我们生活在一个只有4位数的世界里(为了简单起见)。
我们有0100
(+4),一个移位0100 >> 1
将使它成为0010
(+2)。现在,如果我们的数字是1100
(-4;第一个位是符号),则向右移动:1100 >> 1
是1110
(-2)。做个除法,但保持标牌。
因此,如果我们移动31次,我们扔掉最后31位的数字,移动符号的位在最不重要的位置,并保留原来的符号。或者简单地说,拿出31位,把它放到0的位置,扔掉所有其他的东西。
0 00000 ..... 11111
x --------------->0 // x is kept
ignore
第二部分-x >>> 31
是一个无符号移位,意思是当我们移动时,符号不被保留。
例如,0100 >>> 1
(+4)将给您0010
(+2)。到目前为止,没有什么与有符号的shift和上面的例子有什么不同。有趣的是,当数字为负数时:
1100
(-4),我们尝试将它移一次:1100 >>> 1
,因为符号不被保留,所以我们在最有意义的位中放置零并向右移动,从而得到:0110
(+6!)。
在现实中,采取32位进入图片。-4 == 1111...111100
,我们把它移到右边:符号是零,其他的东西都移到右边,例如:0111...11110
或Integer.MAX_VALUE - 1
。
System.out.println(-4 >>> 1);
System.out.println(Integer.MAX_VALUE - 1);
因此,部分x >>> 31
将把符号位移动到最不重要的位置,对其他所有东西进行归零。无论你给它的号码是多少,你都会得到1
或0
。
1 00000 ..... 11111
x --------------->1 // x is "zeroed also"
ignore
将-x
添加到x >>> 31
中只是为了使|
能够正确地工作,以满足我们所需的结果。
https://stackoverflow.com/questions/41717118
复制相似问题