Newsgroup: it.comp.lang.c
Titolo: Domanda

Salve ragazzi!!
Sono un nuovo acquisto del C!
Vengo subito al sodo!
C'e' un modo semplice per tradurre un intero in un numero binario?!?
cioe' passare da 10 a 1010!! Inoltre solo lo standard C99 c'ha stdbool.h
invece in ansi?!? Come lo faccio!!
Non mi linciate per le troppe domande che vi ho fatto!!

 invece in ansi?!? Come lo faccio!!
Se per "ansi" intendi lo standard ISO C89, non c'è.
"Come lo faccio" che cosa ?

Andrea Laforgia wrote:

ho sbagliato con i punti esclamativi... nel senso "Devo farlo a manina??"
si per ansi intendo C89!!
Grazie ancora per lo spunto!!

 ho sbagliato con i punti esclamativi... nel senso "Devo farlo a manina??"
Che cosa ??

 ho sbagliato con i punti esclamativi... nel senso "Devo farlo a manina??"
Scusa, questo e' un NG di C.
Se devi convertire un numero base 10 in base 2 a "manina" non capisco
perche' non hai postato su di un NG di matematica ma su di uno di C.
Lo "spunto" di Andrea funziona benone su di un computer ma non per
prendere spunto su come farlo a mano in quanto usa un trucchetto:
i computer (beh, quelli con cui hai a che fare) tengono i numeri in
memoria in formato binario quindi invece di fare i "calcoli" per
convertire un numero base 10 a base 2 Andrea ha usato gli operatori
bit-a-bit per stampare la rappresentazione interna del numero sul
computer.
Fare i calcoli a mano e' semplicissimo ma devi seguire un altro
algoritmo...
e' 10 divisbile per 2? si, stampo 0 e divido 10 per 2
0
e' 5 divisibile per 2? no, stampo 1 e divido per 2 (divisione intera)
10
e' 2 divisibile per 2? si, stampo 0 e divido per 2
010
e' 1 divisibile per 2? no, stampo 1 e smetto di andare avanti in quanto
sono arrivato all'unita':
1010
ok?
Tommaso
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

Andrea Laforgia wrote:

ok ri-riscrivo daccapo!
Devo tradurre da intero a binario! Come faccio? Devo fare questa conversione
a manina??
Oppure ho capito male io sul tuo "Che cosa ??"
nel senso vorresti sapere "che cosa" sto facendo e a cosa mi serve tradurre
un intero in binario?

 a manina??
Il tuo "come lo faccio" era riferito a stdbool.h e non capivo proprio 
che cosa intendessi.  Per tradurre un numero da intero a binario devi 
scriverti una funzione simile a quella che ti ho postato, non c'è nulla 
di standard.  Il contrario, invece, è possibile farlo in modo standard.

Tommaso Galleri wrote:

Si si... quest'algoritmo lo conosco da un bel pò di tempo!!
Mi chiedevo solo se esisteva una "chicca" del C che facesse in automatico
quello che hai descritto tu! 

 in automatico quello che hai descritto tu!
Allora bisogna che impari a scrivere in Italiano perche' sia Io che
Andrea non abbiamo capito per alcuni posts cosa tu intendessi.
Se invece di "manina" usassi parole meno equivoche...
No, non esiste nessuna "chicca" (perche' poi dovrai usare questi
termini?) del C.
Il C e' un linguaggio piccolo e non ha funzioni di questo genere.
Come hai visto pero' a "manina" non e' molto difficile farlo.
Tommaso
P.S. hai una chicca nella manina?


Andrea Laforgia wrote:

Allora sfrutto un pò della tua conoscenza!
Siccome molto probabilmente mi ritornera' una sequenza in binario mooolto
lunga dovrei ritradurre il tutto come un unico numero gigantesco!
Tipo in binario:
01100111011100100110000101111010011010010110010100100000011000010110110001110100011100100110010101110100011101000110000101101110011101000110111100001010
e in decimale:
2306940726147523927455072570335060930520706826
il che un semplice long non mi aiuterebbe!
In questo caso e' ancora possibile farlo in modo standard?

 a manina??
Tu hai scritto:
"C'e' un modo semplice per tradurre un intero in un numero binario?!?"
Non hai mai chiesto:
"Esiste una funzione gia' fatta che fa parte della libreria standard del
C?"
Il modo semplice esiste ma devi implementarlo tu.
Con semplice non si capiva che intendessi gia' fatto e con "manina"
francamente avevo poi capito che dovessi farlo a mano con carta e penna.
Magari siamo Io ed Andrea poco perspicaci, ma di sicuro tu non ci hai
aiutato a capirti!
Tommmaso


Tommaso Galleri wrote:

Scusatemi! 
La prossima volta sarò piu' preciso e chiaro nelle domande che vi farò! ;)

 In questo caso e' ancora possibile farlo in modo standard?
si, solo che diventa un pochino piu' complessa l'implementazione e devi
fare tante cose a "manina", ma si riescono ovviamente tutte a fare in C
standard.
Tommaso


 In questo caso e' ancora possibile farlo in modo standard?
Se ti basta, puoi usare un "long long", che è standard.
D'altronde nel mio codice basta cambiare il tipo unsigned in long long.

 D'altronde nel mio codice basta cambiare il tipo unsigned in long long.
Gia'!
Peccato che il suo numero binario sia di 152 bits, beh dovra' scrivere
una bella "chicca" di codie oppure usare una libreria gia' fatta per
numeri in precisione arbitraria.
Molte di queste librerie sono scritte in C standard.
Tuttavia scriverlo a mano e' un buon esercizio che gli consiglio.


 
Si si!
Mi invento i programmi col solo gusto di complicarmi la vita! :P
A parte gli scherzi... siccome lo sto imparando da autodidatta ogni idea che
mi viene a mente la uso per creare qualcosa di nuovo! 
Vediamo che riesco ad inventarmi!
Grazie ancora per i consigli!!
Vincenzo

 Peccato che il suo numero binario sia di 152 bits, [...]
Tre long long in cascata... (ovviamente considerando l'endianess della 
macchina)... ;-)

Andrea Laforgia wrote:

purtroppo la lunghezza dei bit e' variabile! cioe' puo' anche essere piu'
lunga di quella che vi ho incollato! :(
vabbe' ci riuscirò!!

 2306940726147523927455072570335060930520706826
In realta:
01100111011100100110000101111010011010010110010100100000011000010110110001110100011100100110010101110100011101000110000101101110011101000110111100001010
in decimale e' proprio:
2306940726147523927455072570335060930520706826
quindi mi sa che tu ci stia prendendo per i fondelli ed abbia gia' 
l'algoritmo giusto, vero?
Beh, in questo caso evito di mandartelo ;-)


Tommaso Galleri wrote:

No no! Non sto prendendo per i fondelli nessuno!! 
Quella che ho pastato e' la traduzione... solo che e' uno script di 10 righe
in bash!!!
Avevo intenzione di farlo in C! Adesso sono arrivato a buttare tutto il
malloppone di zeri e uni in un array di char!!
Per la riconversione e' un pò un macello perche' non so proprio dove mettere
le mani!!
VinX

 le mani!!
Beh, potresti partire dal analizzare il codice bash e vedere come
funziona, a meno che non usi una funzionalita' gia' fatta... (non
conosco bene bash, so solo le basi).


 Tommaso
E' proprio quello che ho fatto!! Diciamo che il grosso e' fatto (almeno del
codice bash)!
Eccolo (con i miei commenti):
--------------------------INIZIO------------------------------
#!/bin/bash
SIZE="$@" # parametro in ingresso!
for i in `seq 1 "${#SIZE}"` 
# sequenza incrementata di 1 fino a ${#SIZE} che e' la lunghezza del
# parametro!
do
        char=$(echo "$@" | cut -b "$i") 
        # contiene il carattere i-esimo del parametro passato in ingresso!
        decimal=$(echo -n "$char" | od -d | sed -n '1s/^[^ ]*
*\([0-9]\+\).*/\1/p')
        # prende il carattere i-esimo lo trasforma in decimale e lo passa ad
        # una regular expression per filtrare l'output
        binary=$binary$(echo "obase=2;$decimal" | bc -l | gawk
'{printf("%08s",$1)}')
        # trasforma il decimale in binario e posiziona il tutto come 
        # [i-1][i]
done
        binary=$binary$(gawk 'BEGIN {printf("%08s",1010)}')
        # aggiunge alla fine 00001010 che in decimale fa 10 che in char
        # equivale allo spazio
        echo $binary
echo "echo $(echo "ibase=2;$binary" | bc -l)P | dc"
# traduce da binario a decimale e ci aggiunge P... infine stampa il
# risultato!
------------------------FINE-----------------------------
Insomma adesso sono arrivato al punto in cui dovrei solo tradurre!
Ossia effettuare questa riga dello script:
echo "echo $(echo "ibase=2;$binary" | bc -l)P | dc"
Il problema e' che e' abbastanza complicatuccio... adesso non so come stai
messo a bash... però bc (preso dal man) e':
        bc - An arbitrary precision calculator language
Il che lascia sottendere che e' un programmone... che un semplice utente se
deve fare ex novo qualche funzionalita' deve sbatterci ben bene la
capoccia! Io lo faccio solo per erudirmi col C... visto che nessuno me l'ha
mai insegnato!
Cmq quello che fa lo script non e' altro che crearti questo numero grosso
che tradotto con il programma dc (an arbitrary precision calculator) ti
ritorna la stringa che hai tradotto! Me l'ha dato una persona che lo usa
per tradurre la sua mail ed evitare lo spam... in modo tale che se qualcuno
deve contattarlo in pvt (e se ci arriva subito) può farlo!
E' un idea carina che volevo mettere in pratica in C! Troppo tosto come
esercizio "base"??!??
VinX

Ok ho capito che la mia ignoranza a riguardo e' tanta!
Adesso sono riuscito a ricalcolarmi "solo" 32 bit... ma oltre non ci vado
(cioe' mi ritorna 0)!!
C'e' una tecnica per prendere piu' memoria (e quindi non allocare solo
32bit) in modo tale da tradurre piu' bit? Cioe' avere un unico grande
valore?!?
Ps: Grazie Manuel!! Solo che non posso risponderti alla mail... mi da questo
errore: Non riuscito; 5.4.3 (errore del server di routing)!!

 valore?!?
Ti ho gią detto che puoi usare "long long". Il problema č che qualsiasi tipo
predefinito di un linguaggio ha una dimensione in bit fissa. Se a te serve
una dimensione variabile, allora hai bisogno di una libreria per lavorare in
aritmetica a precisione multipla:
http://www.swox.com/gmp/index.orig.html
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

 Inviato via 
http://arianna.libero.it/usenet/
Mmmmmm! Allora ho provato a farlo con il long long... solo che stranamente
mi prende solo e sempre i 32 bit e gli altri rimangono a 0!
Sicuramente sbaglierò in qualcosa nel mio codice!
Nel frattempo cambiando il long long con double riesco a far uscire il
risultato esatto (per ora l'ho provata con una stringa di 60 caratteri e
va')! Mi accontento di questa lunghezza dato lo scopo del programma! Cmq mi
darò una sbirciatina al link che mi hai dato!!
Grazie ancora a tutti!!
VinX

 Sicuramente sbaglierò in qualcosa nel mio codice!
Se non ci fai vedere il tuo codice, è impossibile capirlo...
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 
ok eccolo!

VinX wrote:
Ecco che cosa ottengo con il mio programma:
[root@VinXBoX]~/Projects/ScriptSignature # ./sign_dc "ciaocome va??"
echo 2016307662531801427730037420851200P | dc
questo invece e' dello script:
[root@VinXBoX]~/Projects/ScriptSignature # sh sign_dc.sh "ciaocome va??"
echo 2016307662531801528252296916320010P | dc
Purtroppo i valori mi escono sballati e non riesco a capire il perche'!
Sicuramente sara' una cazzata che sbaglio!

 Ecco che cosa ottengo con il mio programma:
<...>
Per "codice" intendevo il sorgente.


 
ma l'ho allegato alla mail precedente!! O_o
vabbe' mo te lo pasto qui:
/* INIZIO */
#include <stdio.h>
#include <stdlib.h>
double power(int num1, int num2);
int strLen(char string[]);
char *concatenate(char array[], char value[]);
char *int2bin(unsigned short value);
char *copy2array(char array[], char value[]);
void binTo10(char binary[],unsigned int value);
int
main(int argc, char *argv[])
{
        int i = 0;
        int length_final = 0;
        int length = strLen(argv[1]);
        char binary[length+1][9];
        char final[(length+1)*8];
        char space[] = { '0', '0', '0', '0', '1', '0', '1', '0', '\0' };
        for(i = 0; i < ((length+1)*8); i++)
                final[i] = '\0';
        if(argc > 2)
        {
                printf("Usage: %s <message>\n", argv[0]);
                return 0;
        }
        for(i = 0; i < length; i++)
        {
                unsigned short decimal = (unsigned short) argv[1][i];
                char *binario = int2bin(decimal);
                copy2array(binary[i], binario);
                free(binario);
        }
        copy2array(binary[length],space);
        for(i = 0; i <= length; i++)
        {
                concatenate(final, binary[i]);
        }
        // printf("%s\n", final); /* debug */
        length_final = strLen(final);
        printf("echo ");
        binTo10(final, length_final);
        printf("P | dc\n");
        return 0;
}
int strLen(char string[])
{
        int i = 0;
        while(1)
        {
                if(string[i] == '\0')
                        return i;
                i++;
        }
}
char *concatenate(char array[], char value[])
{
        int length_arr = strLen(array);
        int length_val = strLen(value);
        int i = 0;
        for(i = 0; i < length_val; i++)
        {
                array[length_arr] = value[i];
                length_arr++;
                array[length_arr] = '\0';
        }
        return array;
}
char *copy2array(char array[], char value[])
{
        int length = strLen(value);
        int i = 0;
        for(i = 0; i < length; i++)
        {
                if(value[i] == '1')
                {
                        int j = 0;
                        int k = length - i - 1;
                        int tmp = 0;
                        for(j = 0; j < (7-k); j++)
                        {
                                tmp = j;
                                array[j] = '0';
                        }
                        tmp++;
                        for(j = i; j < length; j++)
                        {
                                array[tmp] = value[j];
                                tmp++;
                                array[tmp] = '\0';
                        }
                        return array;
                        break;
                }
        }
        return array;
}
char *int2bin(unsigned short ivalue)
{
        size_t nbits= (8 * sizeof ivalue);
        char *result=calloc(nbits+1, 1);
        int i;
        for (i=0; i<nbits; i++)
                result[i]=((ivalue>>(nbits-i-1))&1)?'1':'0';
        return result;
}
double power(int a, int b)
{
        if(b == 0)
                return 1;
        else
                return a*power(a,b-1);
}
void binTo10(char n[],unsigned int l)
{
        int i = 0;
        double s = 0;
        double p[l];
        for (i=0; i<l; i++)
        {
                n[i]=n[i]-'0';
                if(n[i] < 0 || n[i] > 1)
                        return;
                p[i]=n[i]*power(2, (l - i - 1));
                s=s+(double)p[i];
        }
        printf("%.0f", s);
        return;
}
/* FINE */
Compila senza warning con gcc-2.95, gcc3.3, gcc3.4, gcc4.0 gcc4.1 altri
compilatori non ne ho!

         size_t nbits= (8 * sizeof ivalue);
Dovresti usare CHAR_BIT, nessuno ti assicura che un char sia lungo 8 bit.
L'unica cosa sicura è che sia lungo 1 byte.


 L'unica cosa sicura è che sia lungo 1 byte.
si però c'ho fatto la prova con i caratteri in input e c'ho fatto stampare
ogni volta il CHAR_BIT... e' uscito sempre 8... provo a fidarmi!!
Sicuramente se cambio tutto e ci metto quelle "standard" il programma si
autocorreggera' per magia!! 
Be' penso però di rimanere col mio per 2 motivi:
1. e' piu' leggero (almeno penso visto che invece di includere tutta una
libreria ne rigenero il codice almeno in parte)!
2. faccio un ripasso delle varie funzioni principali del C e mi tengo in
allenamento nel correggere gli errori logici!
VinX

 libreria ne rigenero il codice almeno in parte)!
Non č piů leggero č piů lento e inefficiente.


 > ogni volta il CHAR_BIT... e' uscito sempre 8... provo a fidarmi!!
Lo standard del linguaggio prevede che un byte sia _almeno_ di 8 bit.
Oggi un byte è _solitamente_ di 8 bit.
Fidati, senza "provare" a farlo.


 
OK lo faro'!

 allenamento nel correggere gli errori logici!
Sul ripasso ok, ma sul fatto che sia piu` leggero sei sicuramente fuori
strada. Quasi sicuramente la libreria C contiene funzioni ottimizzate
pesantemente (ad esempio le funzioni di copia useranno asm MMX/SSE) e
sono ben testate :)
Luca
-- 
Home: 
http://kronoz.cjb.net
The trouble with computers is that they do what you tell them, 
not what you want.
D. Cohen

int length = strLen(argv[1]);
char binary[length+1][9];
char final[(length+1)*8];
length e' noto solo a run time. Non dovresti utilizzare malloc per
allocare spazio agli array. Il compilatore ha bisogno di conoscere il
valore di lenght a compile time

 length e' noto solo a run time.
No.  Il nuovo standard supporta i VLA (variable length array) supportando
definitivamente ciò che nel C89 non è supportato, ma che molti compilatori
C89-compliant (vedi gcc) supportavano come estensione.


Ho modificato il sorgente!
L'unica cosa che non ho "standardizzato" e' strtol suggerito da Andrea...
(piu' che altro non riesco a capire il doppio puntatore nella
dichiarazione...)!
Il problema alla soluzione persiste ancora! Ma ho scoperto cos'e' che non
va!
La riga di codice incriminata che sbarella e spara stronzate e':
 s = s+(double)p[i];
Il bello e' che nemmeno mi va in overflow la variabile s (potevo anche
capirlo ma 2^190 ci va tranquilla!) e non fa piu' la somma esattamente dopo
53 chiamate (anche se ci deve sommare solo un misero 2 al risultato!!)!!
Mi sembra alquanto stramba sta cosa! Vi e' mai capitata questa cosa?!?

 dichiarazione...)!
Semplice. Il primo puntatore e` la stringa che vuoi convertire. Il
secondo puntatore (che puo` essere NULL) serve per far ritornare
dalla funzione l'indirizzo del primo carattere che non riesce a
convertire.
Esempio.
   char * str = "123pippo";
   char * ch;
   long res;
   res = strtol(str, &ch, 10);
Alla fine di questo codice, res == 123 e ch conterra` l'indirizzo
della prima 'p' di 'pippo' (ossia str+3), quindi
   putchar(*ch);
scrivera` 'p'.
Se non ti serve conoscere questo puntatore, basta passare NULL.
   res = strtol(str, NULL, 10);
Saluti,
Marco
-- 
To email me, remove the no_ and _spam from my address.

Marco Pallante wrote:

Grazie per la spiegazione!! L'ho provato subito... 
ma il risultato non riesce ad andare oltre!!!
ho pensato di provare strtouq ma niente!! Anche in questo modo supero 
il limite per un unsigned long long int!! Vabbe' mi sa che ritorno sui miei
passi e dovro' escogitare un metodo per farmi dare il risultato che mi
serve!!
Grazie ancora!