Newsgroup: it.comp.os.linux.iniziare
Titolo: Conversione da base 16 a base 24

 
Esiste qualcosa di pronto da utilizzare in linux?
Dal canto mi oho provato un po' con "bc".
 
 
Ad esempio, per passare da base 2 a base 16 il numero $INPUT_BIN
si può fare così:
 
---
echo "obase=16; ibase=2; $INPUT_BIN" |bc
---
 
Ma, se volessimo passare da base16 a base24 col seguente comando:
 
---
echo "obase=24; ibase=16; $INPUT_HEX" |bc
---
 
 
Ecco che qualcosa non torna.
Leggendo dal manuale di bc, vedo che seppure la conversione a
base24 in output è consentita, ma per basi in uscita superirori
a 16 bc utilizza una notazione particolare della quale non riesco
a trovarne l'utilità per ottenere finalmente il numero in base24:
 
---
"For bases 2 through 16, the usual method of
writing numbers is used. For bases greater
than 16, bc uses a multi-character digit
method of printing the numbers where each
higher base digit is printed as a base 10
number."
---
 
Eppure ad esempio in rete si trovano facilmente strumenti di
conversione online: inserisci il numero in base16 scegli base24
in uscita e 16 in ingresso e ottieni il risultato.
 
 
D'altra parte in linux esiste il comando "base64" che codifica e
decodifica una stringa, ma quella non credo sia una conversione
di base in senso matematico, o forse sì...
 
Insomma, vi siete mai trovati a dover convertire verso/da base24?
Vi è qualche strumento pronto su linux possibilmente da liea di
comando in modo che sia richiamabile in uno script bash?

Non saprei la risposta, ma da un semplice test
risulta che con b24 i numeri sono rappresentati
da due cifre decimali, invece che lettere e cifre.
 
Ad es., 2==2, 23==23, 24==01 00
Il che ha anche senso.
 
Per mia curiosita` personale: a cosa ti servono
numeri in base 24?
 
bye,
 
pg

-- 
 
piergiorgio

 numeri in base 24?
 
 
Il discorso è un po' complicato. L'utilità anche poca
a dire il vero.  Più che altro è una curiosità mia.
Diciamo che Sono alle prese con una stringa da decodificare
e che per la decodifica deve essere convertita prima in
base24.
 
Se riesco a saltarci fuori poi spiego meglio nel dettaglio
la cosa. Adesso complicherebbe e appesantirebbe sicuramente
il topic portandoci probabilmente anche fuori tema...
 
Ad ogni modo grazie dell'intervento.  :)

 Ad ogni modo grazie dell'intervento.  :)
 
E` sempre possibile fare la conversione "a mano".
 
Le cifre b24 sono il resto della divisione (ricorsiva)
per 24, del numero in b10.
 
X=1000
while [ $X -gt 0 ]
do
  B=$(( $X % 24 ))
  X=$(( X / 24 ))
  echo $B
done
 
Questo ti ritorna, in ordine inverso ed in b10, la
rappresentazione di X (1000 in questo esempio) in b24.
 
Per avere quello che vuoi tu, devi creare un array A,
con valori da 0 a N ed usare A(B) (in ordine corretto).
 
bye,
 
-- 
 
piergiorgio

 
 
Capisco, niente di pronto insomma  che tu/voi sappiate.

 Capisco, niente di pronto insomma  che tu/voi sappiate.
 
Non ne sono a conoscenza, anche se vedo un "base64",
che fa l'encode/decode in quello *standard*, come
definito in RFC 3548.
 
La domanda sarebbe se b24 e` definito da qualche
parte, magari esiste una qualche libreria perl o
python che si occupa della cosa.
 
bye,
 
-- 
 
piergiorgio

 python che si occupa della cosa.
 
 
Probabilmente ho risolto con bc.
Quello che bc convertendo da base16 a base24 fà è sputare un numero
composto da coppie decimali di bit.
 
In realtà ciascuna coppia "XX" significa "il numero di posizione XX
nella non definita ipotetica notazione base24".
 
Facciamo un esempio... (quegli esempi che spesso mancoano nelle pagine
man!!  :D ).
 
Abbiamo il seguente numero esadecimale da convertire in una ipotetica
notazione base24 costittuita appunto da 24 simboli che andremo poi a
definire.
 
base16  = 7300790053005C0074006F006F0052
 
se chiamiamo HEX una variabile contenente il numero esadecimale
soprariportato, possiamo ottenere la versione "bc" del corrispondente
base24.
 
B24=$(echo "obase=24;ibase=16;$HEX" |bc |tr -d '\\' |tr -d '\n')
 
Ecco cosa ottengo, lo scrivo su due righe
 
$ echo $B24
18 15 16 23 14 17 00 19 12 18 10 10 09 \
12 06 12 04 08 06 04 05 12 13 01 00 18
 
Questo numero non è un numero in base24 perchè non è composto da 24
simboli.. e come osservavi in effetti se non c'è uno standard che
definisce quali siano questi simboli c'è poco da fare: il povero bc
non può mica inventarsi le cose...
 
Allora si limita a dirci che ad esempio:
 
- la prima cifra del nostro numero in base 24 sarà 
  il 18-esimo simbolo del nostra notazione base24.
 
- la seconda cifra sarà il 15-esimo simbolo
 
...e così via.
 
Quindi una volta definita la notazione, cioè i 24 simboli, ecco
che possiamo sostituire a ciascuna coppia numerica del base24
restituito da bc, il corrispondente simbolo base24.
 
Pre fare questo basta la bash a sto punto...
 
$B24 è il nostro numero da convertire e possiamo chiamare
$MAP24 la nostra serie di 24 simboli.
 
Siamo noi/io a definire quali siano questi simboli facciamo
solo un esempio:
 
MAP24=0123456789ABCDEFGHIJKLMN
 
Il ragionamento che si può fare è questo:
 
per ogni coppia di cifre di $B24, pesca il corrispondente
ennesimo simbolo dalla stringa MAP24.
 
Bisogna fare attenzione però perchè 'ennesimo' deve essere
un'intero, invee alcune coppie numeriche sono del tipo:
00
09
06
04
08
...
 
Insomma iniziano con "zero" e bisogna prima convertirle in
numeri interi.
 
ci può soccorrere ancora una volta bc:
 
echo 00|bc ---> 0
echo 09|bc ---> 9
 
Per pescare l'ennesimo simbolo da MAP24 ho trovato questo
metodo in bash:
 
${MAP24:$ennesimo:1}
 
Ad esempio il primo numero di B24 è la coppia "18",
volendo stampare il simbolo corrispondente basterà:
 
echo ${MAP24:18:1}
 
Mettendo insieme tutti i tasselli, la soluzione in bash
potrebbe essere anche banale.
Prendiamo HEX in input come primo argomento:
 
 
---
#!/bin/sh
 
MAP24=0123456789ABCDEFGHIJKLMN
HEX=$1
B24=$(echo "obase=24;ibase=16;$HEX" |bc |tr -d '\\' |tr -d '\n')
for i in $B24
do
        i=$(echo $i|bc)
        echo $i ${MAP24:$i:1}
        OUT24=${OUT24}${MAP24:$i:1}
done
echo
echo HEX = $HEX
echo BC 24 = $B24
echo BASE-24 = $OUT24
---
 
 
 
Facciamo una prova:
 
---
$ b24.sh 7300790053005C0074006F006F0052
18 I
15 F
16 G
23 N
14 E
17 H
0 0
19 J
12 C
18 I
10 A
10 A
9 9
12 C
6 6
12 C
4 4
8 8
6 6
4 4
5 5
12 C
13 D
1 1
0 0
18 I
 
HEX = 7300790053005C0074006F006F0052
BC 24 = 18 15 16 23 14 17 00 19 12 18 10 10 09 12 06 12 04 08 06 04 05
12 13 01 00 18
BASE-24 = IFGNEH0JCIAA9C6C48645CD10I
---
 
Sarà giusto?
Al servizio online che avevo riportato risulta diverso:
IFGNEH0JCIAG000G880G080080
 
 
Ho scritto un'esagerazione!!!  8O

 IFGNEH0JCIAG000G880G080080
 
A me da':
ifgneh0jciaa9c6c48645c1310i
 
Quindi a ognuno un risultato diverso... brutto segno!
 
Da me e' difficile un errore con sed, guarda.
1) file "per_sed"
-----------
s/10/a/g
s/11/b/g
s/12/c/g
s/13/d/g
s/14/e/g
s/15/f/g
s/16/g/g
s/17/h/g
s/18/i/g
s/19/j/g
s/20/k/g
s/21/l/g
s/22/m/g
s/23/n/g
s/00/0/g
s/01/1/g
s/02/2/g
s/03/3/g
s/04/4/g
s/05/5/g
s/06/6/g
s/07/7/g
s/08/8/g
s/09/9/g
---------------
(tu le vuoi maiuscole, io le odio -- a parte che come dice Piergiorgio
le minuscole si confondono di meno)
 
Riga di comando:
echo "ibase=16; obase=24; 7300790053005C0074006F006F0052" | bc \
| sed -f per_sed | tr -d '0 '
 
Ecco cosa esce:
34g292933bc5253f24e728h9e25aj418
Dunque errore in input, in bc devi entrare con base 10, penso.
 
Allora prima traduco, poi do:
echo "obase=24; 597123725439511943426976473504743506" | bc \
| sed -f per_sed | tr -d ' '
 
ifgneh0jciaa9c6c48645c1\
310i
 
(va be' i backslash di bc li sai togliere ho visto)
 
Ciao e fammi sapere
 
-- 
Tanti saluti
 

 310i
 
cioè su una riga:
 
ifgneh0jciaa9c6c48645c1310i
 
Il problema sta nell'output di bc.
Tu lo passi direttamente a sed. nonostante contengaa un backslash e un
"a capo" (aka newline == \n ).
Secondo me questo infastidisce un po' sed, guardiamo l'output grezzo:
---
$ echo "obase=24;ibase="16"; 7300790053005C0074006F006F0052"|bc
 18 15 16 23 14 17 00 19 12 18 10 10 09 12 06 12 04 08 06 04 05 12 1\
 3 01 00 18
---
 
Vedi il problema è che il numero viene tagliato dividendo una coppia
di cifre "13" che diventa:
1\
3
 
quando sed lavora su queste, le interpreta come due cifre da convertire
invece è solo una.
infatti nel tuo risultato trovi
 
*c-13-10
 
Mentre nel mio:
 
*c-d-10i
 
In altre parole tu hai due cifre 1 e 3 mentre io che avevo un "13"
traduco correttamente in "d" oppure "D" in upper case.
 
Soluzione e morale della favola:
dare a sed in pasto un numero vero e non un output splittato
alla carlona con backsalsh e a capo a casaccio.
 
In altre parole:
Aggiungi in pipe tr -d '\n' e tr -d '\\':
 
---
$ echo "obase=24;ibase="16"; 7300790053005C0074006F006F0052"|bc
 18 15 16 23 14 17 00 19 12 18 10 10 09 12 06 12 04 08 06 04 05 12 1\
3 01 00 18
 
$ echo "obase=24;ibase="16"; 7300790053005C0074006F006F0052"|bc|sed -f per_sed
 i f g n e h 0 j c i a a 9 c 6 c 4 8 6 4 5 c 1\
3 1 0 i
---
 
Errato!
 
---
echo "obase=24;ibase="16"; 7300790053005C0074006F006F0052"|bc \
                         |tr -d '\\' \
			 |tr -d '\n'
18 15 16 23 14 17 00 19 12 18 10 10 09 12 06 12 04 08 06 04 05 12 13 01 00 18
 
$ echo "obase=24;ibase="16"; 7300790053005C0074006F006F0052" \
      |bc|tr -d '\\' \
      |tr -d '\n'    \
      |sed -f per_sed
 i f g n e h 0 j c i a a 9 c 6 c 4 8 6 4 5 c d 1 0 i
---
 
Giusto..
Aggiungi anche il tr -d ' ' finale e ottieni il numero senza spazi.
 
Detto questo forse dovrebbe essere più efficiente la versione senza sed
che pesca il numero NN dalla stringa di mappatura base24. Ma non sono
sicurissimo perchè poi comunque richiede il ciclo for.
Ad ogni modo se no si devono convertire cose grandissime dovrebbe essere
equivalente...
 
Grazie comunque dell'idea

 a trovarne l'utilità per ottenere finalmente il numero in base24:
 
Ho provato a dare in bc un obase=101 oltre a ibase=10 e il bello è che
funziona e per:
 
100, restituisce:
 100
 
per:
101, restituisce:
 001 000
 
ovviamente per numeri come obase=un milione penso funzioni altrettanto
bene :)
-- 
Sandro kensan 
www.kensan.it
 & 
www.qiqi.it
 geek site
Saluto gli agenti della NSA - Hello NSA - 
www.nsa.gov
 

 bene :)
 
Mica tanto ovviamente, infatti dando un'occhiata al manuale... ;)
man bc:
---
LIMITS
       The following are the limits currently in place for
       this bc processor. Some of them may have been changed
       by an installation. Use the limits statement to see
       the actual val‐ ues.
 
       BC_BASE_MAX
              The maximum output base is currently set at
              999. The maximum input base is 16.
---
 
In pratica accetta in ingresso basi fino a 16 e in uscita fino
a 999.
 
Volendo fare il giochino inverso (conversione da base24 a base 16
anche giusto per verifica è già un casino:
---
echo "obase=16; ibase=24 $BASE24"|bc
---
 
Banalmente non funzica, non l'ho testato, ma si dovrebbe incorrere
nel limite "ibase > 16".

 a 999.
 
Ho provato:
ibase=10
obase=10^6
10^6+1
 000001 000001
 
...funziona.
 
Non ho provato con un miliardo... :)
