C # Primero 1 (de derecha a izquierda) en número binario

10

Estoy tratando de usar C # para encontrar el índice del primer 1 (de derecha a izquierda) en la representación binaria de un número. Por ejemplo, dado que 100 en binario es:

0b1100100

El primer 1 está en la tercera posición desde la derecha, por lo que debería producir 3.

234 debería producir 2, 0 debería producir 0, etc.

Aquí está mi solución actual:

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

¿Alguna forma de acortar esto?

Eric Cepress
fuente
1
El consejo obvio es eliminar tu espacio en blanco extraño. Veo 10 espacios que puedes eliminar fácilmente.
James
Convert.ToString(k,2).IndexOf("1")es lo que quieres, o algo similar, un sitio incorrecto.
Magic Octopus Urn
14
@ votantes cercanos - ¿Por qué los votos cerrados? Creo que esta es una pregunta sobre consejos sobre el tema . ¿O ha habido cambios en las reglas que me he perdido en este sentido?
Trauma digital

Respuestas:

3

Si solo C # admite intrínsecos específicos de la máquina ... Hay una sola instrucción que puede hacer esto en lenguaje ensamblador x86, y también en la mayoría de las arquitecturas de otros procesadores. Entonces no solo tendría el código más corto, sino muy probablemente el más rápido.

De hecho, hacer que este código sea más corto es un problema extremadamente aburrido en comparación con hacer que este código sea rápido . Hay todo tipo de soluciones realmente ordenadas, eficientes y poco complicadas, y también podría considerar usar una tabla de búsqueda.

Sin embargo, nada de eso importa para el golf. Me parece que su solución actual es lo mejor que puede hacer. Por supuesto, puede eliminar el espacio en blanco superfluo:

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

Yo personalmente lo escribiría como:

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

porque creo que es un poco más claro tener la dirección de la prueba condicional de esa manera, así como compararla con cero, pero supongo que son seis en una dirección, media docena en la otra.

C # no admite la conversión implícita de inta boolC y C ++, por lo que realmente no puede acortar más la prueba condicional.

También está atascado con la conversión explícita de double(como devuelto mi Math.Log) a int, ya que C # no permitirá que esto suceda implícitamente. Por supuesto, eso normalmente es bueno porque señalaría que tiene un gran problema de rendimiento aquí: promocionar inta a a double, calcular el registro de a doubley luego convertir el doubleresultado a a intserá enormemente lento, por lo que normalmente es algo que te gustaría evitar Pero estos son los tipos de perversiones que tienes que soportar cuando juegas golf de código.


Inicialmente se me ocurrió

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

(sin pretensiones de claridad, por supuesto), lo que evita tomar el logaritmo y, por lo tanto, es una mejora en el tamaño y la velocidad del código. Desafortunadamente, esto no siempre obtiene la respuesta correcta, y supongo que es un requisito inflexible. :-) Específicamente, falla si el valor de entrada ( k) es un factor de 8. Esto es reparable, pero no sin hacer que el código sea más largo que la Math.Logversión.

Cody Gray
fuente
Tenga en cuenta que para el código de golf, Mathdebería estar completamente calificado, por lo que su otra versión debería ser mejor, aunque en realidad no he contado los bytes.
TheLethalCoder
¿Te refieres al que produce la salida incorrecta? @the
Cody Gray
Bueno, dijiste que hay una solución, pero lo haría más largo. Si la solución es más corta que cuando la versión de OP incluye, System.entonces debería ser más corta y correcta.
TheLethalCoder