Algoritmos de computação se um número for múltiplo de 3

13

Ao fazer cálculo mental, pode-se fazer:

  • Dado um número inteiro k, some todos os dígitos (na base 10) e, se o resultado for múltiplo de 3, k será múltiplo de 3.

Você conhece algum algoritmo funcionando de maneira semelhante, mas operando com dígitos de números binários (bits)?

  • No começo, eu estava pensando em usar as funções prontas da minha linguagem convertendo número inteiro para ascii para realizar a conversão da base 2 para a base 10 e depois aplicar o truque de cálculo mental. Mas é claro que eu também poderia codificar a conversão de base 2 para 10. Ainda não o fiz, mas vou tentar.

  • Então eu pensei na divisão euclidiana na base 2 ...

No entanto, gostaria de saber se existem outros meios, algoritmos.

Stephane Rolland
fonte
2
Você pode achar que é interessante: Projeto DFA aceitar cadeias binárias divisível por um número 'n'
Grijesh Chauhan

Respostas:

22

Considere as duas observações a seguir (deixadas como um exercício para o leitor):

  1. Os poderes pares de dois são 1 módulo 3.
  2. Os poderes ímpares de dois são -1 módulo 3.

Concluímos que um número (em binário) é divisível por três se e somente se a soma dos bits nas posições pares for igual à soma dos bits nas posições ímpares módulo 3.

mhum
fonte
7
É como a regra de ser divisível por 11 em decimal.
Yuval Filmus
1
@YuvalFilmus: Precisamente. Eu acrescentaria outro exercício para o leitor, mas decidi contra.
Mhum
3
OK, que tal descobrir se um número escrito em hexadecimal é divisível por 17 (decimal)? Ou 15 (decimal) para esse assunto? ;-)
vonbrand 27/01
33

Que tal um autômato de estado finito para o trabalho?

insira a descrição da imagem aqui

É claro que a mágica é apenas o módulo de computação 3. A adição do símbolo a string por trás x significa que o "valor binário" da string vai de v a l ( x ) para x a 2 v a l ( x ) + a para x a . Consequentemente, do estado pe símbolo a passamos para o estado 2 p + a mod 3 , para p { 0 , 1 , 2axval(x)x2val(x)+axapa2p+amod3 e um { 0 , 1 } . Nota x { 0 , 1 } é uma string, sendo que v a l ( x ) N é seu valor como string binária.p{0,1,2}a{0,1}x{0,1}val(x)N

Hendrik Jan
fonte
1
Eu gosto da idéia, vamos tentar com 9. Eu alimento 1001 em binário. O primeiro bit me envia ao estado1, depois ao estado2, depois ao estado1 e depois ao estado0. Portanto, state0 é múltiplo de 3. E a complexidade do algoritmo é o número de bits usados, nada mais. É incrivel !
precisa saber é o seguinte
Esse conceito no link está relacionado? Eu acho que é mais simples. geomathry.wordpress.com/2017/02/13/0-1-and-a-new-number
1
0¯0=0¯0¯1=1¯1¯0=2¯1¯1=0¯2¯0=1¯2¯1=2¯Θ,1,01,2,0
Não sobre programação. Isso será mais eficiente em um computador ternário?
4

Em binário, os números 1, 100, 10000 (= 100 × 100), 1000000 (= 100 × 100 × 100) etc. todos fornecem o mesmo restante após a divisão por 11 (três). Portanto, se dividirmos um número binário em partes de comprimento par , a soma das partes fornecerá o mesmo restante que o número original.

(Ao dividir o número, adicionamos quantos zeros forem necessários ao início . Por exemplo, dividiríamos 10111 nos grupos 01,01,11 ou 0001,0111.)

Matematicamente, apenas divida o número em grupos de dois dígitos e adicione os grupos; e repita isso até que o resultado se torne 00 ou 11 = o número original era um múltiplo de três; ou 01 ou 10 = o número original não era um múltiplo de três.

Para um programa de computador, o uso de grupos de oito, dezesseis ou trinta e dois bits pode ser mais rápido para sua CPU. Por exemplo, se a adição de oito bits for mais rápida, faça uma soma de todos os bytes e, novamente, até que o resultado caiba em um byte. Em seguida, use uma instrução para determinar o restante depois de dividir por três.

(Observação: estamos assumindo números inteiros não assinados aqui. Com um número assinado, ele precisa de um pouco mais de atenção. Por exemplo, 129 é um múltiplo de 3, mas -127 não, embora os bits 10000001 signifiquem ex como um byte não assinado e este último como um byte assinado.)

Viliam Búr
fonte
0

Embora não seja específico do binário, na dúvida, a subtração repetida é sempre uma maneira infalível de calcular a divisão com o restante (e, portanto, se um número for múltiplo de 3).

jmite
fonte
2
Subtração repetida é uma má ideia. A divisão com o restante é muito mais rápida.
Yuval Filmus
3
provavelmente realmente muito caro na CPU, mas é um algoritmo diferente :-) que não merece -1 :-(
Stephane Rolland