Algoritmos computacionales si un número es múltiplo de 3

13

Al hacer cálculo mental, uno puede hacer:

  • Dado un entero k, sume todos los dígitos (en base 10), y si el resultado es un múltiplo de 3, entonces k es un múltiplo de 3.

¿Conoces algún algoritmo que funcione de manera similar pero que funcione con dígitos (bits) de números binarios?

  • Al principio, estaba pensando en usar las funciones preparadas de mi lenguaje para convertir enteros a ascii para realizar la conversión de la base 2 a la base 10, luego aplicar el truco de cálculo mental. Pero, por supuesto, también podría codificar yo mismo la conversión de base 2 a 10. Todavía no lo he hecho, pero lo intentaré.

  • Entonces he pensado en la división euclidiana en la base 2 ...

Sin embargo, me pregunto si hay otros medios, algoritmos.

Stephane Rolland
fuente
2
Puede que le resulte interesante: Diseñe DFA aceptando cadenas binarias divisibles por un número 'n'
Grijesh Chauhan

Respuestas:

22

Considere las siguientes dos observaciones (dejadas como ejercicio para el lector):

  1. Los poderes pares de dos son 1 módulo 3.
  2. Las potencias impares de dos son -1 módulo 3.

Concluimos que un número (en binario) es divisible por tres si y solo si la suma de los bits en las posiciones pares es igual a la suma de los bits en las posiciones impares módulo 3.

mhum
fuente
77
Esto es como la regla para ser divisible por 11 en decimal.
Yuval Filmus
1
@YuvalFilmus: Precisamente. Iba a agregar otro ejercicio para el lector pero decidí no hacerlo.
mhum
3
Bien, ¿qué tal si descubrimos si un número escrito en hexadecimal es divisible por 17 (decimal)? ¿O 15 (decimal) para el caso? ;-)
vonbrand
33

¿Qué pasa con un autómata de estado finito para el trabajo?

ingrese la descripción de la imagen aquí

Por supuesto, la magia es solo el módulo de cálculo 3. Agregar el símbolo detrás de la cadena x significa que el "valor binario" de la cadena va de v a l ( x ) para x a 2 v a l ( x ) + a para x a . En consecuencia, desde el estado p y el símbolo a, pasamos al estado 2 p + a mod 3 , para p { 0 , 1 , 2unXvunl(X)X2vunl(X)+unXunpagun2pag+unmodificación3 y un { 0 , 1 } . Nota x { 0 , 1 } es una cadena, mientras que v a l ( x ) N es su valor como cadena binaria.pag{0 0,1,2}un{0 0,1}X{0 0,1}vunl(X)norte

Hendrik Jan
fuente
1
Me gusta la idea, intentemos con 9. Alimento 1001 en binario. El primer bit me envía al estado1, luego al estado2, luego al estado1 y luego al estado0. Entonces state0 es múltiplo de 3. Y la complejidad del algoritmo es el número de bits utilizados, nada más. Es impresionante !
Stephane Rolland
¿Está relacionado este concepto en el enlace? Creo que es más simple. geomathry.wordpress.com/2017/02/13/0-1-and-a-new-number
1
@WaqarAhmad Sí, relacionado, no más simple. Las transiciones en un autómata finito también se pueden usar para describir una evaluación L2R, como en su explicación. Las transiciones definen , ˉ 0 1 = ˉ 1 , ˉ 1 0 = ˉ 2 , ˉ 1 1 = ˉ 0 , ˉ 2 0 = ˉ 1 , ˉ 2 1 = ˉ 20 0¯0 0=0 0¯0 0¯1=1¯1¯0 0=2¯1¯1=0 0¯2¯0 0=1¯2¯1=2¯. Aquí tenemos tres estados, por lo que son necesarios tres símbolos para los estados. Sus símbolos son las evaluaciones de los números módulo 1 , 2 , 0 respectivamente, y el primer símbolo en su evaluación L2R es el "estado". Si desea una discusión, ¡quizás sea mejor comenzar una nueva pregunta en el sitio! Θ,1,0 01,2,0 0
Hendrik ene
No sobre programación. ¿Será esto más eficiente en una computadora ternaria?
4

En binario, los números 1, 100, 10000 (= 100 × 100), 1000000 (= 100 × 100 × 100) etc. todos dan el mismo resto después de dividir por 11 (tres). Por lo tanto, si dividimos un número binario en partes de longitud par , la suma de las partes da el mismo resto que el número original.

(Al dividir el número, agregamos tantos ceros como sea necesario al principio . Por ejemplo, dividiríamos 10111 en los grupos 01,01,11 o 0001,0111).

Matemáticamente, simplemente divida el número en grupos de dos dígitos, luego agregue los grupos; y repita esto hasta que su resultado sea 00 u 11 = el número original era un múltiplo de tres; o 01 o 10 = el número original no era un múltiplo de tres.

Para un programa de computadora, el uso de grupos de ocho o seis años o treinta y dos bits puede ser más rápido para su CPU. Por ejemplo, si la adición de ocho bits es más rápida, simplemente haga una suma de todos los bytes, y nuevamente, hasta que el resultado encaje en un byte. Luego, use una instrucción para determinar el resto después de dividir por tres.

(Nota: aquí estamos asumiendo enteros sin signo . Con un número con signo, necesita un poco más de atención. Por ejemplo, 129 es un múltiplo de 3, pero -127 no lo es, aunque los bits 10000001 significan para el primero como un byte sin signo y este último como un byte firmado).

Viliam Búr
fuente
0

Si bien no es específico de binario, en caso de duda, la resta repetida es siempre una forma segura de calcular la división con el resto (y, por lo tanto, si un número es múltiplo de 3).

jmite
fuente
2
La resta repetida es una mala idea. La división con el resto es mucho más rápida.
Yuval Filmus
3
probablemente realmente muy costoso en la CPU, pero es un algoritmo diferente :-) que no merece -1 :-(
Stephane Rolland