Newsgroup: it.comp.lang.c
Titolo: problema union

salve a tutti
ho un quesito da porre:
utilizzando una union di questo tipo
  union
  {
   long a;
   long b;
   double c;
  } u;
volendo utilizzare solo le variabili u.a e u.b come posso arrivare a 
modificare i bit piu' a destra della variabile double?
Grazie mille

pardon piu' a sinistra :)


Manuel ha scritto:

Eh!?
--
Cingar
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 modificare i bit piu' a destra della variabile double?
Agendo con i normali operatori bitwise su /a/ e /b/. Il problema e` che
non sai a priori il formato del double ed inoltre tali modifiche
porterebbero ad un risultato indefinito (a norma di standard, se poi
conosci il formato usato e sei sicuro che le modifiche che fai sono
corrette allora e` ok).
Luca
-- 
Home: 
http://kronoz.cjb.net
Io mi ricordo sempre il compleanno della mia ragazza:
cade il giorno dopo di quando lei me lo ricorda

Conosco il modo in cui vengono memorizzati i double, ora voglio mettere 
i bit a caso in una variabile double, per poi gestire gli eventuali INF 
o NaN.
Ho utilizzato la tua union
union {
         struct {
                 long a;
                 long b;
         } c;
         double d;
} u;
poi ho fatto cosi'
for(i=1;i<=16;i++)
{
u.c.a = u.c.a|rand()%2; //metto un bit nella prima posizione
u.c.a = u.c.a<<1; //leftshift
}
for(i=1;i<=16;i++)
{
u.c.b = u.c.b|rand()%2; //metto un bit nella prima posizione
u.c.b = u.c.b<<1; //leftshift
}
ma mi accorgo sempre che a è sempre piu' grande di b
e che il double poi è sempre uguale a 0
Esempio:
a
long address 0022FF88
value 703151528
b
long address 0022FF8C
value 55366
d
double address 0022FF88
value 0.000000
Il mio dubbio ora è sul fatto che la variabile b rimane sempre di 5 
cifre mentre a è sempre di 9, e il fatto che questi cambiamenti non 
influiscano sulla variabile d mi lascia ancora piu' perplesso


 influiscano sulla variabile d mi lascia ancora piu' perplesso
Anche a me il double assume sempre valore 0, ma a questo forse c'è una
spiegazione.
Se non vado errato, i 64 bit di double in formato IEEE, dovrebbero essere
strutturati in questa modo (da sinistra a destra):
- 52 bit di mantissa,
- 11 bit di esponente,
- 1 bit di segno.
Se non ho fatto male i calcoli, ipotizzando un'architettura little-endian
(come nei processori Intel), i 32 bit generati dai tuoi due loop finiscono
*TUTTI* nella mantissa. Perciò l'esponente rimane zero.
Il valore del double è Mantissa*(2^Esponente) e, di conseguenza, il valore
del double sarà sempre zero. 
Non ho capito perché riempi solo 16 bit di ogni long: se tu li riempi
tutti e 32, per un totale di 64, vedrai che otterrai valori diversi da
zero.


 
hemm...proprio ci devo far attenzione a certe cose :)

Anche riempiendo i long di tutti e 32 bit il double è sempre zero :(

Anzi no, viene zero spesso e volentieri, come sia naturale credo :P


 influiscano sulla variabile d mi lascia ancora piu' perplesso
Prima di tutto rand() genera numeri *pseudocasuali*, se la sequenza non
viene inizializzata con valori diversi essa non varia. Al momento non
ricordo alla perfezione lo std IEEE e non mi metto a fare le conversioni
a mano dei numeri casuali ;)
Comunque se vai per passi dovresti chiarire il tutto. Inizia con inf,
che si ottiene mettendo a 1 tutti i bit dell'esponente e a 0 tutto il
resto. I bit dell'esponente sono 11, quindi il valore esadecimale
corrispondente e` 0x7ff. Scritto byte per byte, in little-endian
dovrebbe essere cosi`:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 f f 7
(Il segno e` a zero, quindi e` +inf)
Ora, ricordando che little-endian significa che il byte meno
significativo e` posto all'indirizzo piu` basso e ricomponendo la
sequenza di byte in due unsigned long ottieni:
0x00000000 0x7ff00000
Quindi:
u.c.a = 0x7ff00000;
u.c.b = 0x00000000;
Per ottenere il NaN basta procedere come prima e poi settare un
qualunque bit della mantissa a 1 (il segno non ricordo... dovrebbe
essere indifferente). Ad esempio:
u.c.a = 0x7ff00000;
u.c.b = 0x00000001;
Luca
-- 
Home: 
http://kronoz.cjb.net
Il coraggio non mi manca.
E` la paura che mi frega...

 u.c.b = 0x00000001;
Idem
...questo a dimostrazione che giocare bit a bit con i floating points
puo` nuocere alla salute mentale ;)
Luca
-- 
Home: 
http://kronoz.cjb.net
Alcuni pensano che io sia una persona orribile, ma non e` vero. Ho il
cuore di un ragazzino - in un vaso sulla scrivania.