Algoritmi che calcolano se un numero è un multiplo di 3


13

Quando si esegue il calcolo mentale si può fare:

  • Dato un numero intero k, sommare tutte le cifre (in base 10) e se il risultato è un multiplo di 3, allora k è un multiplo di 3.

Conosci qualche algoritmo che funziona in modo simile ma che funziona su cifre (bit) di numeri binari?

  • Inizialmente, stavo pensando di usare le funzioni già pronte del mio linguaggio per convertire numeri interi in ascii per eseguire la conversione dalla base 2 alla base 10, quindi applicare il trucco del calcolo mentale. Ma ovviamente potrei anche codificare me stesso la conversione base da 2 a 10. Non l'ho ancora fatto, ma ci proverò.

  • Poi ho pensato alla divisione euclidea nella base 2 ...

Tuttavia mi chiedo se ci siano altri mezzi, algoritmi.


Risposte:


22

Considera le seguenti due osservazioni (lasciate come esercizio al lettore):

  1. I poteri pari di due sono 1 modulo 3.
  2. I poteri dispari di due sono -1 modulo 3.

Concludiamo che un numero (in binario) è divisibile per tre se e solo se la somma dei bit nelle posizioni pari è uguale alla somma dei bit nelle posizioni dispari modulo 3.


7
Questo è come la regola per essere divisibile per 11 in decimale.
Yuval Filmus,

1
@YuvalFilmus: precisamente. Stavo per aggiungere un altro esercizio per il lettore, ma ho deciso di non farlo.
mamma l'

3
OK, che ne dici di scoprire se un numero scritto in esadecimale è divisibile per 17 (decimale)? O 15 (decimale) per quella materia? ;-)
vonbrand il

33

Che dire di un automa a stati finiti per il lavoro?

enter image description here

Ovviamente la magia è solo il calcolo modulo 3. L'aggiunta del simbolo dietro la stringa x significa che il "valore binario" della stringa va da v a l ( x ) per x a 2 v a l ( x ) + a per x a . Di conseguenza dallo stato p e dal simbolo a ci spostiamo allo stato 2 p + a mod 3 , per p { 0 , 1 , 2axval(x)x2val(x)+axapa2p+amod3 e un { 0 , 1 } . Nota x { 0 , 1 } è una stringa, dove v a l ( x ) N è il suo valore come stringa binaria.p{0,1,2}a{0,1}x{0,1}val(x)N


1
Mi piace l'idea, proviamo con 9. Nutro 1001 in binario. Il primo bit mi invia a state1, quindi state2, quindi state1 quindi torna a state0. Quindi state0 è multiplo di 3. E la complessità dell'algoritmo è il numero di bit utilizzati, niente di più. È meraviglioso !
Stephane Rolland,

Questo concetto nel collegamento è correlato? Penso che sia più semplice. geomathry.wordpress.com/2017/02/13/0-1-and-a-new-number

1
@WaqarAhmad Sì, correlato, non più semplice. Le transizioni in un automa finito possono anche essere usate per descrivere una valutazione L2R, come nella tua spiegazione. Le transizioni definiscono , ˉ 0 1 = ˉ 1 , ˉ 1 0 = ˉ 2 , ˉ 1 1 = ˉ 0 , ˉ 2 0 = ˉ 1 , ˉ 2 1 = ˉ 20¯0=0¯0¯1=1¯1¯0=2¯1¯1=0¯2¯0=1¯2¯1=2¯. Qui abbiamo tre stati, quindi sono necessari tre simboli per gli stati. I tuoi simboli sono le valutazioni dei numeri modulo 1 , 2 , 0 rispettivamente, e il primo simbolo nella tua valutazione L2R è lo "stato". Se vuoi una discussione, forse è meglio iniziare una nuova domanda sul sito! Θ,1,01,2,0
Hendrik Jan

Non parlare di programmazione. Questa cosa sarà più efficiente in un computer ternario?

4

In binario, i numeri 1, 100, 10000 (= 100 × 100), 1000000 (= 100 × 100 × 100) ecc. Danno tutti lo stesso resto dopo aver diviso per 11 (tre). Pertanto, se dividiamo un numero binario in parti di lunghezza pari , la somma delle parti fornisce lo stesso resto del numero originale.

(Quando si divide il numero, si aggiungono tutti gli zeri necessari all'inizio . Ad esempio, si dividerebbe 10111 nei gruppi 01,01,11 o 0001,0111.)

Matematicamente, basta dividere il numero in gruppi di due cifre, quindi aggiungere i gruppi; e ripeti fino a quando il risultato diventa 00 o 11 = il numero originale era un multiplo di tre; o 01 o 10 = il numero originale non era un multiplo di tre.

Per un programma per computer, l'utilizzo di gruppi di otto o sei settanta o trentadue bit potrebbe essere più veloce per la tua CPU. Ad esempio, se l'aggiunta a otto bit è la più veloce, basta sommare tutti i byte e ancora, fino a quando il risultato non si adatta a un byte. Quindi utilizzare un'istruzione per determinare il resto dopo aver diviso per tre.

(Nota: qui assumiamo numeri interi senza segno. Con un numero con segno , richiede un po 'più di attenzione. Ad esempio 129 è un multiplo di 3, ma -127 non lo è, sebbene i bit 10000001 significino per ex come byte senza segno e quest'ultimo come byte con segno.)


0

Sebbene non sia specifico per i binari, in caso di dubbio, la sottrazione ripetuta è sempre un modo infallibile per calcolare la divisione con resto (e quindi se un numero è un multiplo di 3).


2
La sottrazione ripetuta è una cattiva idea. La divisione con il resto è molto più veloce.
Yuval Filmus,

3
probabilmente è davvero molto costoso in cpu, ma è un algoritmo diverso :-) che non merita -1 :-(
Stephane Rolland
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.