java - 赋值,但仅限于正数 - 无条件

标签 java math integer conditional-statements

问题

xor-swap algorithm 这样的技巧给我留下了深刻的印象和类似的。所以我问自己,是否可以为变量分配一个值,但前提是该值为正数 - 不使用任何类型的 if 或隐藏条件;只是纯数学

替代方案

基本上,这但没有 if:

int a = ...
int b = ...

if (b >= 0) {
    a = b;
}

示例

以下是一些示例输入/输出设置,用于说明所需的逻辑:

a = 1, b = 10 -> a = 10 // b is positive
a = 1, b = 0 -> a = 0   // b is 0, also positive
a = 1, b = -10 -> a = 1 // b is negative

最佳答案

tl;博士

int a = ...
int b = ...

int isNegative = b >>> 31;       // 1 if negative, 0 if positive
int isPositive = 1 - isNegative; // 0 if negative, 1 if positive
a = isPositive * b + isNegative * a;

签名


完成该任务的一个简单方法是尝试获取某种signum ,或者更具体地说是一种获得因子

的方法
  • 要么 0,如果 b
  • 如果 b,则为 1,反之亦然。

现在,如果您看一下 int 在内部如何用 32 位表示(这称为 Two's complement ):

// 1234
00000000 00000000 00000100 11010010
// -1234
11111111 11111111 11111011 00101110

您会看到它的最左侧有所谓的符号位,即 most-significant-bit 。事实证明,您可以通过简单的位移轻松提取该位,只需将整个位模式向右移动 31 次,只留下第 32 位,即符号位:

int isNegative = b >>> 31; // 1 if negative, 0 if positive

现在,要获得相反的方向,只需对其取反并在其顶部添加 1 即可:

int isPositive = 1 - isNegative; // 0 if negative, 1 if positive

AnnihilatorIdentity

一旦掌握了这一点,您就可以通过利用以下事实轻松构建您想要的值

  • 0 相乘基本上会删除参数(0*annihilator)
  • 0 相加不会改变该值(0+identity 元素)。

那么,回到我们首先想要实现的逻辑:

  • 如果 b 为正,我们需要 b
  • 如果 b 为负,我们需要 a

因此,我们只需执行 b * isPositivea * isNegative 并将它们相加即可:

a = isPositive * b + isNegative * a;

现在,如果 b 为正,您将得到:

a = 1 * b + 0 * a
  = b + 0
  = b

如果是负数,你会得到:

a = 0 * b + 1 * a
  = 0 + a
  = a

其他数据类型

同样的方法也可以应用于任何其他带符号的数据类型,例如byteshortlongfloat double

例如,以下是 double 的版本:

double a = ...
double b = ...

long isNegative = Double.doubleToLongBits(b) >>> 63;
long isPositive = 1 - isNegative;
a = isPositive * b + isNegative * a;

不幸的是,在Java中你不能直接在double上使用>>>(因为弄乱指数和尾数通常也没有意义),但因此你有 helper Double#doubleToLongBits它基本上将 double 重新解释为 long

关于java - 赋值,但仅限于正数 - 无条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69227706/

相关文章:

java - Netty 流 URL/输入流

algorithm - 多个球体内的点

JavaScript:获取日期差异并将月份转换为年份

仅用一个整数表示一组整数的算法

java - google face API 对所有图像的处理速度很慢?

Java:获取当前的星期几值

java - Amazon Elasticache Redis 集群 - 无法获取端点

algorithm - 如何将数字表示为 4 个素数之和?

c++ - 将两个整数合并为一个并稍后对其进行解码

c++ - 指针问题