繁体   English   中英

如果输入大于零,是否有单线从输入中减去1?

[英]Is there a one-liner for subtracting 1 from an input if the input is greater than zero?

也许我忘记了一个巧妙的按位运算,但是有一种更聪明的方式来表达以下内容吗?

int r = foo(); // returns an int
r -= r > 0; // same as `if(r > 0) r--;`

我想将线条组合成一个表达式。

最易读的方式是最聪明的方式:

if (r > 0)
    --r;

它具有可读性,并且最有可能产生最快的代码-因为许多开发人员并没有徒劳地尝试看起来很聪明,并且创建优化编译器的人检测到了通用模式并对其进行了优化。

就个人而言,我希望if (r > 0) r--; 为了提高可读性,但如果您确实想避免使用条件:

r = r > 0 ? r-1 : r;

仍然是有条件的分配,或者:

r > 0 && r--;

要么:

r <= 0 || r--;

之所以可行,是因为如果左侧已经确定了结果,则不会执行右侧。

顺便说一句,不要指望任何性能差异。 大多数编译器将从所有这些选项中生成或多或少等效的代码。

如果测试r> = 0,则一种可能性是隔离符号位,然后减去(1-signBit)。

在C语言中,是这样的(但我想这可以转换成多种语言)

int r = foo();
return r - (int)((~ ((unsigned) r)) >> (sizeof(r)*8-1));

当然,您现在依赖于int的内部表示,并且大大混淆了代码...

对于r> 0,则涉及更多...也许像

unsigned int r = foo();
return (int) (r - ((~(r | (r-1))) >> (sizeof(r)*8-1)));

我什至没有尝试过这些片段,答案是很有趣的,但是如果您认真对待,您将不得不提供大量的解释来证明这种黑客行为是合理的,包括测试,生成的代码分析和基准测试。

如果像这样的每个次要操作都经过这样的过程,那么编写代码将是一件痛苦的事情,对于必须维护它的人(阅读/理解/扩展...)来说,这将是一个痛苦。 我希望这不是过早的优化,在这种情况下,也许正确的决定是编写一小块汇编程序。

好吧,例如,对于具有2补码的32位整数,这样的操作可能会起作用(未经测试!)

const int mask = 1 << 31;

int r = foo();

r -= ((r ^ mask) >> 31);

基本上,您检查最左边的位是否为零,如果最左边的位为零,则将其转换为1,否则仍为零,然后对其进行移位,以使正数为1,负数为0,然后减去

暂无
暂无

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

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