Re-writing code to remove conditional statements
是否可以重新编写以下内容,使其不包含任何条件语句?我想可能有一些巧妙的技巧,比如位运算?
1 2 3 4 5 6 7 8 9 10
| int a = // some value
int b = // some other value between 0 and max int
if(b >= 3)
{
return a + 1;
}
else
{
return a;
} |
编辑:要明确一点,我不是在寻找一种删除条件的通用方法。我正在寻找一个技巧来从这个非常具体的代码中删除条件。把它当作一个学术难题。
举个例子,删除条件(在某些情况下会产生性能提升)的一种方法是预先计算一个查找表,并使用b将其索引到该表中。在这种特殊情况下,这是很棘手的,因为b可能是一个非常大的数字。还有别的办法吗?
- 为什么用一些更模糊的位操作替换清晰易懂的代码?如果是的话,代码可读性很重要。如果你在考虑性能…想想如果你真的需要节省几个时钟周期:我想你不会注意到一百万次迭代中的任何差异。
- 当然可以。这很容易:从return b>>x==y?z<. Tadaaaaa.
-
Is it not okay to ask a question like"is this possible"? Or put another way, is it necessary to know why I would want to do this in order to answer whether it is possible or not?
-
@GianPaolo it is for performance reasons in fact, and it can totally make a difference when you have a lot of iterations.
-
Ok. let me tell you something. You want to count from 1到1000000000000。计算这个最快的方法是什么?江户十一〔二〕号?不。答案是根本不要这样做。如果你想让你的程序运行得更快,你必须寻找其他部分,或者可能寻找更好的方法来实现你想要的。
- @拉齐兰,你能帮我解开那行密码吗?也许是作为答案而不是评论?
- @卡兹马卡里先生,对不起,我不明白你的论点。(我几乎不能阻止你告诉我一些事情。)
- @本很确定种族主义所发表的是一个笑话,它不是有效的代码。不过,关键是,大多数人都同意,您选择了错误的性能优化,分支速度非常快。
- @Ronbyer嗯,也许是的。尽管他们不断地在c中添加奇怪的新操作符…
- 我认为,@m.kazem-akhgary,你不应该假设知道我使用所述代码的情况(它是一个相当于.NET 2 via mono的Unity游戏中非常大的紧环)。上下文很重要。
- @本,你的代码是最快的。您需要的是计算1 + 1 = 2,而不添加1+1。这是不可能的,需要完成1+1。实际上,条件只是一个字节。但是位操作需要在ALU中计算4个字节。另外,三元体较短,但似乎较慢。看看这里stackoverflow.com/questions/17328641/&hellip;
- 本,就像罗恩说的,这是个笑话。但真正的问题是:你要求的是最短的代码还是最快的代码?因为当你说尽管他们不断地在c中添加奇怪的新操作符时,你说的大多是更短而不是更快。是的,我完全同意你的观点,但是你忘了在你的问题中提到非常重要的"语境"。你应该说有没有更快的代码…,答案是没有。你发布的代码是最快的方法。任何其他代码都会变慢,保证。
- @拉齐兰是的,你说得对,这一定是个笑话(因此我的"尽管他们……"线-也是一个笑话)。我认为你误解了我对"上下文关系"的使用:我所指的上下文是代码所在的位置、运行的平台、使用的是什么JIT编译器等等。这些上下文都没有问题,因为它们是无关的。我的问题纯粹是"能做到吗?".这与性能有关的事实并不相关-对于任何已发布的答案,无论如何检查本地系统的性能都是很容易的。
- 是的,我完全理解你的上下文,我同意。然而,性能是非常相关的,而且实际上是必需的,因为没有它,你的问题"它能做到"就没有意义了。当然可以。每件事都可以用不同的方式来做,但真正的问题是"能用更好的方式来做吗",而现在"更好的"需要一个"更好的方式"的语境。这反映在你对韩国回答"这在某种意义上更好"的评论中。所以底线是"它能以不同的方式完成吗?"当然可以。"能更快吗?"不,它不能。
- 明白了,但要说清楚,我从来没有要求过更好的方法。我还没有看到一种不使用分支的不同方式。我相信这可能是可以做到的,如果我能做到的话,我很肯定我能在我的环境中获得性能优势。也许我错了,但我想要一个机会尝试,所以我真的不想陷入一个预先的性能讨论。
干得好
1
| return a - ((2 - b) >> 31); |
说明:
r = 2 - b, < 0 (i.e. high bit set) for b >= 3
r >> 31, = -1 for b >= 3, 0 otherwise
< /块引用>
1 2 3 4
| uint a = // some value
uint b = // some other value between 0 and max int
bool c = b & 0xFFFC
return a + Convert.ToInt32(c); |
最快的可能是位运算速度非常快
1 2 3
| uint a = // some value
uint b = // some other value between 0 and max int
return (b & 0xFFFC) ? a+1 : a; |
- 是啊。你解除了这种状况。但这要慢一点;)
- 只是找点乐子
- 谢谢你回答问题@daves。我会根据我的具体情况检查性能。
- 无论如何,convert.toint32将作为三元运算符内联
- dotnetperls.com/convert-bool-int
- 我想你可以把它和一个查找表结合起来避免最后的三元运算。
?:运算符。(但它包含条件语句。)
1
| return b >= 3 ? a + 1 : a; |
或
1
| return a + (b >= 3 ? 1 : 0); |
Is it possible to re-write the following so that it doesn't contain any conditional statements?
不可能在哪里解决问题。你必须以任何方式检查这种情况。没有魔法。
如果您想通过删除这个条件使程序更快,那么您选择了错误的方法。这是微观优化。
你可以通过这样做来改善它:
1 2 3
| int a = // some value
int b = // some other value between 0 and max int
return (b >= 3) ? (a+1) : a; |
- 更好的是,代码行更少,但在某种意义上,这只是"更好的"(不一定是合理的)。