隔离最左边的1位

时间:2013-01-25 10:43:27

标签: javascript binary

我正在寻找以二进制方式隔离最右边的东西:

我得到了这个解决方案:

y = x & (-x)

所以:

    10111100  (x)
&   01000100  (-x)
    --------
    00000100

但是现在,我想通过找到最多数字来找到数字的大小(虽然不是符号......)

如何详细说明我的解决方案找到最左边的位?

示例:

10 1 11100

0 1 000100

2 个答案:

答案 0 :(得分:4)

没有类似的O(1)按位技巧来查找数字的大小。许多微处理器指令集包括一个“计算前导零”的特殊指令。 C语言系列中没有这样的运算符,它为JavaScript提供了按位功能。

唯一的O(1)替代方案是使用Math.floor( Math.log( n ) / Math.LN2 )快速试用

for ( var i = 0; i == Math.floor( Math.log( 1<<i ) / Math.LN2 ); ++ i ) ;
由于i == 31运算符使用32位二进制补码运算,

结果为<<

如果你想成为一个纯粹主义者,你可以反复右移一个,即O(log n),或者你可以反复右移16 >> i,{{1从0到4,当结果为零时拒绝移位,否则累积i。那就是O(log log N),其中N是16 >> i的最大可能值,这意味着恒定时间,但很可能慢于n

O(log log N)算法的代码:

Math.log

当然,对于其中任何一个,你必须通过结果左移一个来获得“最左边的1位”而不是索引。

编辑:注意,基于var mag = function( n ) { var acc = 0; for ( var i = 16; i; i >>= 1 ) { if ( n >> i ) { n >>= i; acc += i; } } return acc; }; 的实现返回log为零,而-Infinity函数返回mag,这是相同的作为0的结果。如果你想要考虑不存在最左边1位的可能性,那么最好将其作为特殊情况。

答案 1 :(得分:1)

由于Math.floor( Math.log( n ) / Math.LN2 )Math.log不是基本操作,我认为public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); final MediaPlayer mp = MediaPlayer.create(this, R.raw.firsteps); mp.start(); DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); drawer.setDrawerListener(toggle); toggle.syncState(); NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); navigationView.setItemIconTintList(null); navigationView.setNavigationItemSelectedListener(this); FragmentManager fm = getSupportFragmentManager(); fm.beginTransaction().replace(R.id.content_frame, new MainFragment()).commit(); } @Override public void onBackPressed() { DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); if (drawer.isDrawerOpen(GravityCompat.START)) { drawer.closeDrawer(GravityCompat.START); } else { super.onBackPressed(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { startActivity(new Intent(getApplicationContext(),Testing.class)); return true; } return super.onOptionsItemSelected(item); } @SuppressWarnings("StatementWithEmptyBody") @Override public boolean onNavigationItemSelected(MenuItem item) { //final MediaPlayer mp = MediaPlayer.create(this, R.raw.xlophone); FragmentManager fm = getSupportFragmentManager(); int id = item.getItemId(); if (id == R.id.car_stories) { fm.beginTransaction().replace(R.id.content_frame,new ChildrensList()).commit(); //mp.start(); } else if (id == R.id.car_places) { fm.beginTransaction().replace(R.id.content_frame,new ImportFragment()).commit(); //mp.start(); } else if (id == R.id.nav_slideshow) { } else if (id == R.id.nav_manage) { } else if (id == R.id.nav_share) { } else if (id == R.id.nav_send) { } DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); drawer.closeDrawer(GravityCompat.START); return true; } } 不是O(1)。

所以,按照定理说你不能得到最左边的1位: “当且仅当结果的每个位仅取决于每个输入操作数的右侧和右侧的位时,可以使用字并行加,减,和,而不是指令来实现将字映射到字的函数。”< / p>

这个定理在“黑客的喜悦”(Henry S. Warren,Jr。)一书的第13页上。