C#二进制数的第一个1(从右到左)


10

我正在尝试使用C#在数字的二进制表示形式中找到第一个1(从右到左)的索引。例如,由于二进制中的100为:

0b1100100

第一个1在右边的第三位置,因此它应该产生3。

234应该产生2,0应该产生0,依此类推。

这是我当前的解决方案:

k < 1 ? 0 :(int)Math.Log(k & -k, 2) + 1;

有什么办法可以缩短它的时间?


1
显而易见的技巧是删除无关的空格。我看到您可以轻松删除的10个空格。
詹姆斯(James)

Convert.ToString(k,2).IndexOf("1")是您想要的,还是类似的错误站点。
魔术

14
@ close-voters-为什么要投票?我认为这是一个热门的提示问题。还是在这方面我错过了任何规则更改?
Digital Trauma

Answers:


3

如果仅C#支持特定于机器的内部函数…,则只有一条指令可以使用x86汇编语言以及大多数其他处理器体系结构执行此操作。这样,您不仅会拥有最短的代码,而且很有可能会拥有最快的代码。

事实上,这使得代码更短的是相比于使这个代码进行非常无聊的问题。有各种各样非常整洁,有效,按位排列的解决方案,您也可以考虑使用查找表。

不过,这与打高尔夫球无关。在我看来,您当前的解决方案是您可以做到的最佳方法。当然,您可以删除多余的空格:

k<1?0:(int)Math.Log(k&-k,2)+1

我个人将其写为:

k>0?(int)Math.Log(k&-k,2)+1:0

因为我认为以这种方式进行条件测试的方向以及将其与零进行比较会稍微清楚一些,但是我想这是一种方法的六种方法,另一种方法的六种方法。

C#不像C和C ++那样支持从int到的隐式转换bool,因此您不能再进一步缩短条件测试的时间。

您还受困于从double(返回my Math.Log)到的显式强制转换int,因为C#不允许隐式发生这种情况。当然,这通常是一件好事,因为它会指出,你有很大的性能问题就在这里:促进一intdouble,计算的日志double,然后转换double结果返回到的int将是大量慢,所以这是正常的东西您想要避免的。但是,这是在玩代码高尔夫时必须忍受的那种变态。


我最初想出了

k > 0
      ? ((k & -k) >> 1) + 1
      : 0

(当然,为清楚起见,请取消注释),这避免了采用对数,因此可以提高代码大小和速度。不幸的是,这并不总是能得到正确的答案,我认为这是一个不灵活的要求。:-)特别是,如果输入值(k)是8的因子,它将失败Math.Log


请注意,对于代码高尔夫球Math,它必须完全合格,因此尽管我实际上没有计算字节数,但其他版本应该更好。
TheLethalCoder

您是说产生错误输出的那个?@the
Cody Gray

好吧,您说有修复程序,但是会使它更长。如果此修复程序比包含OPs版本的修复程序短System.,则应更短且正确。
TheLethalCoder
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.