Problema con variabile double[C]

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Problema con variabile double[C]

Messaggio da gila75 »

Ciao ragazzi, non capisco una cosa:
Ho fatto un programma che dato un numero double (minore di 1 e maggiore di 0), lo passa a una funzione.
La funzione lo esamina, se minore di 0.5 mette una S (sinistra) in un array di char, se maggiore mette D (destra), e uguale a 0 mette C (centro).
Dopo averlo fatto, la funzione riprende il numero e lo raddoppia, se sfora 1, taglia la parte intera:
Es:
0.8=1.6

Prende solo 0.6, quindi verrà scritto D nell'array.

0.25=S
0.25*2=0.5 (C)
0.5*2=1-1=0 (C) fine, non ci si muove più

il problema è che dopo un po' di cicli, il numero double, perde di precisione es:
0.72*2=1.44

a me restituisce al posto di 0.44 il numero 0.440001
Perchè questi arrotondamenti?
Lo avevo già notato tempo fa scrivendo un programma per bambini che faceva le equivalenze, usando i float, ma non ci avevo dato molto peso.
Questo è un output partendo dal numero 0.33:
Spoiler
Mostra
XXXX 0.660000
XXXX 0.320000
XXXX 0.640000
XXXX 0.280000
XXXX 0.560000
XXXX 0.120000
XXXX 0.240000
XXXX 0.480000
XXXX 0.960000
XXXX 0.920000
XXXX 0.840000
XXXX 0.680000
XXXX 0.360000
XXXX 0.720000
XXXX 0.440000
XXXX 0.880000
XXXX 0.760000
XXXX 0.520000
XXXX 0.040000
XXXX 0.080000
XXXX 0.160000
XXXX 0.320000
XXXX 0.640000
XXXX 0.280000
XXXX 0.560000
XXXX 0.120000
XXXX 0.240000
XXXX 0.480000
XXXX 0.960000
XXXX 0.920000
XXXX 0.840000
XXXX 0.680000
XXXX 0.360000
XXXX 0.720000
XXXX 0.440001
XXXX 0.880001
XXXX 0.760002
XXXX 0.520004
XXXX 0.040009
XXXX 0.080017
XXXX 0.160034
XXXX 0.320068
XXXX 0.640137
XXXX 0.280273
XXXX 0.560547
XXXX 0.121094
XXXX 0.242188
XXXX 0.484375
XXXX 0.968750
XXXX 0.937500
XXXX 0.875000
XXXX 0.750000
XXXX 0.500000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
e questa è una bozza del programma, se può aiutare.

Codice: Seleziona tutto

#include <string.h>                                       
#include <stdlib.h>
#include <stdio.h>

void particella_uno (char array_1[], double a);


void particella_uno (char array_1[],  double a)
{
    int i;
    for (i=0; i<100; i++)
    {
        
        if (a<0.5)
        {
            array_1[i]='S';
        }
        if (a>0.5)
        {
             array_1[i]='D';
        }

        if (a==0)
        {
            array_1[i]='C';
            
        }
        
        a=a*2;
        
        if (a>=1)
        {
            a=a-1;
            
        }
        printf ("%lf\n",a);
    }

     for (i=0; i<100; i++)
          printf ("%c",array_1[i]);
    return;
}
//***************************************************************




int main(void)
{
    double a=0.33; 
    
    char array_1[100]={};
   
    particella_uno (array_1,a);
    
    return 0;
}           
Mi serve per fare degli esperimenti di un libro che sto leggendo, riguardo a frattali, teoria del caos e roba del genere, mi piacerebbe fare delle prove.
Grazie a tutti :)
Avatar utente
SuperStep
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 2037
Iscrizione: lunedì 19 dicembre 2011, 16:26
Desktop: Unity
Distribuzione: Ubuntu 16.04 LTS x86_64
Sesso: Maschile
Località: Somma Vesuviana (NA)

Re: Problema con variabile double[C]

Messaggio da SuperStep »

significa che la floating point unit che utilizzi approssima per difetto o per eccesso, in informatica e' impossibile rappresentare numeri infiniti dopo la virgola, quindi la floating point unit li taglia, ecco il perche- di questi arrotondamenti.
ubuntu 16.04 LTS 64-bit - Memoria: 31,3 Gib - Processore: Intel Core i7-5960X CPU @ 3.00 GHz × 16 - Grafica: AMD Radeon HD 7800 Series - Disco: SSD 256 GB x 4 (RAID 01)
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Problema con variabile double[C]

Messaggio da gila75 »

Grazie SuperStep, ma non si tratta di un numero con moltissimi decimali.
si parte da 0.33 non che so io... 0.3256874592567.
Cavolo, se uno deve scrivere un programma con un minimo di precisione che fa?
E poi, se hai dato un occhio allo spoiler, che contiene l'output, inizia a sbagliare dopo molti raddoppiamenti, non subito.

Rimetto lo spoiler e ho segnato da dove inizia a "ciccare" :
Spoiler
Mostra
0.33 numero iniziale

XXXX 0.660000
XXXX 0.320000
XXXX 0.640000
XXXX 0.280000
XXXX 0.560000
XXXX 0.120000
XXXX 0.240000
XXXX 0.480000
XXXX 0.960000
XXXX 0.920000
XXXX 0.840000
XXXX 0.680000
XXXX 0.360000
XXXX 0.720000
XXXX 0.440000
XXXX 0.880000
XXXX 0.760000
XXXX 0.520000
XXXX 0.040000
XXXX 0.080000
XXXX 0.160000
XXXX 0.320000
XXXX 0.640000
XXXX 0.280000
XXXX 0.560000
XXXX 0.120000
XXXX 0.240000
XXXX 0.480000
XXXX 0.960000
XXXX 0.920000
XXXX 0.840000
XXXX 0.680000
XXXX 0.360000
XXXX 0.720000
XXXX 0.440001 Qui Inizia a "sbaglaire
XXXX 0.880001
XXXX 0.760002
XXXX 0.520004
XXXX 0.040009
XXXX 0.080017
XXXX 0.160034
XXXX 0.320068
XXXX 0.640137
XXXX 0.280273
XXXX 0.560547
XXXX 0.121094
XXXX 0.242188
XXXX 0.484375
XXXX 0.968750
XXXX 0.937500
XXXX 0.875000
XXXX 0.750000
XXXX 0.500000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
XXXX 0.000000
Le XXXX non centrano nulla...non farci caso.
Avatar utente
M_A_W_ 1968
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 856
Iscrizione: venerdì 15 febbraio 2013, 3:57
Desktop: KDE
Distribuzione: SuSE
Sesso: Maschile
Località: Un luogo geometrico
Contatti:

Re: Problema con variabile double[C]

Messaggio da M_A_W_ 1968 »

Devi assolutamente leggere questo.
Il formato floating point IEEE 754 va bene in teoria per taluni utilizzi (anche se dopo oltre trent'anni di pratica dell'informatica, almeno venti dei quali spesi ronzando attorno al mondo del calcolo numerico avanzato e/o in tempo reale, farei comunque fatica ad elencare quali siano codesti fantomatici utilizzi, ma cerchiamo di fingerci diplomatici... :lol: ), ma quando le cose si fanno un tantino serie occorre passare ad apposite librerie decimal floating point IEEE 854 (sono quelle usate quando ci sono di mezzo i quattrini, dunque dove le approssimazioni non sono accettabili), oppure per altri utilizzi si può profilare l'uso di formati con precisione arbitraria, i quali per quanto ti riguarda si limitano a spostare il problema connaturato con il binary floating point (come la colf svogliata che spazza la polvere sotto il tappeto, è sempre lì ma almeno non ci si pesta sopra).

In ultima analisi, il linguaggio C "right out of the box" è paradossalmente molto meno "scientifico" e orientato al calcolo numerico esatto rispetto a linguaggi normalmente considerati vergognosi per usi scientifici, come i vari visual basic o quel simpatico dinosauro del COBOL - i quali, essendo appunto nati specificamente per l'area burotico-amministrativa, incorporano librerie di tutto rispetto per quanto attiene l'eliminazione delle approssimazioni. In realtà, per l'ennesima volta, la natura semitrasparente del C in quanto (unico) linguaggio di livello intermedio non fa altro che esporre arcaiche limitazioni concettuali e architetturali della piattaforma x86 e di tutte quelle ad essa ispirate.
Ora, mettendoti una mano in tasca, se ti ci trovi qualche spicciolo (è una cifretta con cinque o sei zeri...), puoi sempre metterti un casa uno Z9 IBM che implementa in hardware il formato IEEE 854 ossia il decimal floating point che ti serve per portare a termine il tuo programmino di esempio. Ah, dimenticavo: la licenza del compilatore C, in quel caso, te la regalano loro... :lol:
Sì, un blog ce l'ho perfino io: gli è che mi manca il tempo...

"...in una società che sembra sempre più spaventata dai problemi troppo articolati e che rigetta come un corpo estraneo ogni elemento di complessità, sapremo ancora come utilizzare il parere degli esperti?"
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Problema con variabile double[C]

Messaggio da gila75 »

Grazie M_A_W, capisco allora che la cosa non è così semplice, e che non è legata a qualche mio errore nel programmino.
Quello che mi dici di leggere e capire (come ben saprai) è lontano anni e anni luce da me.
Ciò non toglie che ci proverò lo stesso.
Purtroppo quel minimo errore, nel programmino che ho steso, porta a risultati completamente sballati nella previsione dei salti D,S,C.
Calcolatrice alla mano, con 0.33, dovrei arrivare dopo un tot di raddoppiamenti ad avere una situazione ciclica.
Es
DDSSSDDDSDSSDD e poi ripartire : DDSSSDDDSDSSDD

So che sembra un programma stupido, ma ci sono molte cose interessanti proposte dal libro che dicevo, e provarle con mano affascina.
Non sono un matematico, ma il fascino misterioso dei numeri e della matematica contenuta nella natura e fenomeni fisici è una cosa da perderci la testa.
Tornando a noi M_A_W, prima di leggere e studiare il link, è fattibile la cosa (per me) o vado contro un muro insormontabile?
Intanto grazie mille :)
Avatar utente
M_A_W_ 1968
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 856
Iscrizione: venerdì 15 febbraio 2013, 3:57
Desktop: KDE
Distribuzione: SuSE
Sesso: Maschile
Località: Un luogo geometrico
Contatti:

Re: Problema con variabile double[C]

Messaggio da M_A_W_ 1968 »

gila75 [url=http://forum.ubuntu-it.org/viewtopic.php?p=4580032#p4580032][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img] ha scritto:Tornando a noi M_A_W, prima di leggere e studiare il link, è fattibile la cosa (per me) o vado contro un muro insormontabile?
Non solo è fattibile, ma anche necessario: potrai imparare, ad esempio, che i confronti che coinvolgono numeri float e double non si svolgono come si farebbe per valori interi, ma usando esplicitamente una differenza tra la variabile che si intende controllare e una appropriata costante, e verificando poi che tale differenza sia sufficientemente piccola... ;)
Sì, un blog ce l'ho perfino io: gli è che mi manca il tempo...

"...in una società che sembra sempre più spaventata dai problemi troppo articolati e che rigetta come un corpo estraneo ogni elemento di complessità, sapremo ancora come utilizzare il parere degli esperti?"
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Problema con variabile double[C]

Messaggio da gila75 »

Leggerò con cura...sempre che riesca con l'inglese tecnico.
Ai miei tempi l'inglese si riduceva a : Hello, my name is Frank...oppure Good morning Mr Robinson, come in!
Quindi farò fatica.
Ma la cosa m'interessa parecchio, anche quando giocherellavo coi pic, mi ero messo a guardare i floating points, mantissa e robe varie.
Comunque, sempre per puro divertimento, ho scritto due righe, che per il mio scopo sarebbero appropriate.
Per eliminare gli arrotondamenti ho fatto i calcoli io usando un array di interi, che simulano un numero double.
Logicamente va bene solo per il mio scopo, è impensabile fare 3.1548 *2569.0009 come ho fatto io.
Comunque questo è il listato.. funziona per quello che dovevo fare
Lo so M_A_W che non approvi :D ma è anche bello giocare.
Appena riesco mi metto a leggere il link :

Codice: Seleziona tutto

#include <string.h>                                       
#include <stdlib.h>
#include <stdio.h>
#define N 15





int main(void)
{
   
    
    int array[N]={0,3,3};
    int i;
    int rip=0;
    int temp;
    int x;

    for (x=0; x<1000; x++)
    {

        for (i=N-1; i>=0; i--)
        {
            temp=(array[i]*2)+rip;
            if (temp>=10)
            {
                rip=1;
                array[i]=(temp-10);
            }  
            else
            {   
                array[i]=temp;
                rip=0;
            }
            
            temp=array[0];
            array[0]=array[0]-temp;
        }




        for (i=0; i<N; i++)
        {
            if (i==1)
                printf (".");
            printf ("%d",array[i]);
        }

        printf ("\n");
    } 
    return 0;
}           
Avatar utente
Claudio_F
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1463
Iscrizione: lunedì 28 maggio 2012, 18:49
Desktop: Mate/Gnome
Distribuzione: Ubu22.04

Re: Problema con variabile double[C]

Messaggio da Claudio_F »

gila75 ha scritto: è impensabile fare 3.1548 *2569.0009 come ho fatto io.
Dipende solo dalla rappresentazione che usi. Con l'aritmetica BCD non c'è nessuna difficoltà, e neppure moltiplicando e dividendo i termini e i risultati per opportuni coefficienti in modo da effettuare calcoli esclusivamente con interi (certo anche molto grandi.. potrebbero eccedere le possibilità di un PIC midrange).

Altre volte si possono fare delle semplificazioni, ad esempio:
0.5 * 60 / (N * 7E-6)

si può riscrivere semplicemente:
4285714 / N
:ciao:
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Problema con variabile double[C]

Messaggio da gila75 »

Ciao Claudio
e neppure moltiplicando e dividendo i termini e i risultati per opportuni coefficienti in modo da effettuare calcoli esclusivamente con interi
Si, coi pic usavo questa tecnica, per non scomodare i floating points, visto che in asm non credo sia una passeggiata:

22/3.4=6.47

si può benissimo fare

22000/34=647

poi aggiustiamo le virgole. Questo dici?
Avatar utente
Claudio_F
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1463
Iscrizione: lunedì 28 maggio 2012, 18:49
Desktop: Mate/Gnome
Distribuzione: Ubu22.04

Re: Problema con variabile double[C]

Messaggio da Claudio_F »

Si, intendo quello, nota che i coefficienti non devono necessariamente essere potenze di dieci, potresti anche moltiplicare per 2 alla 32, e alla fine l'aggiustamento della virgola non richiederebbe divisioni per 10 ma semplici shift a destra di N bit.

Si può però ripresentare il "problema" di questo topic che è un limite intrinseco della rappresentazione binaria con un numero finito di bit... quando l'ho scoperto anni fa col Pascal un collega mi prendeva in giro dicendo che il suo BASIC non faceva certe cose, e ricordo ancora la sua faccia basita quando gli ho dimostrato il contrario :D

Il fatto è che semplicemente l'epsilon di macchina introduce un errore percentuale solitamente molto piccolo rispetto alle grandezze che interessa maneggiare: il fatto che la lunghezza di un muro risulti di un metro e due micrometri invece che un metro non fa alcuna differenza pratica (soprattutto per il manovale :lol:).
:ciao:
Avatar utente
M_A_W_ 1968
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 856
Iscrizione: venerdì 15 febbraio 2013, 3:57
Desktop: KDE
Distribuzione: SuSE
Sesso: Maschile
Località: Un luogo geometrico
Contatti:

Re: Problema con variabile double[C]

Messaggio da M_A_W_ 1968 »

gila75 [url=http://forum.ubuntu-it.org/viewtopic.php?p=4580114#p4580114][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:Si, coi pic usavo questa tecnica, per non scomodare i floating points, visto che in asm non credo sia una passeggiata:

22/3.4=6.47

si può benissimo fare

22000/34=647

poi aggiustiamo le virgole. Questo dici?
Si chiama calcolo in virgola fissa. C'è una marea di letteratura in merito: restando nell'ambito che conosci, i PIC, c'era un'ottima application note, la AN617, basata su un paio di veri e propri capolavori nel mondo del calcolo binario, come il Cavanagh. In seguito anche Microchip, come da decenni hanno fatto gli altri grandi nomi dell'embedded, ha iniziato a proporre librerie e generatori di codice, pur con tutti i relativi limiti di utilizzo.

In generale, una delle prime cose che spiego ai miei studenti suona come segue: nel mondo del firmware embedded gli unici che usano il floating point sono i dilettanti più confusi, e qualche incolpevole professionista che si trovi per qualche motivo costretto a farlo (sempre su una idonea piattaforma, s'intende, come un DSP o un motion controller dedicato tipo Magellan). Si stima che non vi sia in letteratura più di un 1-2% di problemi numerici realtime (interpolazioni, cinematica inversa, balistica...) che non possano risolversi con una appropriata combinazione di aritmetica intera, razionale e fixed point.

Peraltro la scelta della risoluzione è sempre nelle capaci mani del progettista... inutile implementare una divisione fixed point di 32 su 32 bit quando si conosce in anticipo il range degli operandi, ad esempio 24 bit su una costante esprimibile con 16!

Tutto ciò si applica anche in casi meno fortunati rispetto al sottoscritto, che possiede un livello di competenza in campo elettronico e microelettronico non inferiore a quello matematico e informatico e quindi è naturalmente eletto a ruoli architetturali, il che si traduce nella possibilità di effettuare il codesign dei sistemi in modo realmente parallelo e interdipendente "usando una sola testa". :lol:
Sì, un blog ce l'ho perfino io: gli è che mi manca il tempo...

"...in una società che sembra sempre più spaventata dai problemi troppo articolati e che rigetta come un corpo estraneo ogni elemento di complessità, sapremo ancora come utilizzare il parere degli esperti?"
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Problema con variabile double[C]

Messaggio da gila75 »

Capisco M_A_W, in effetti quando avevo programmato un radar a ultrasuoni, per fare un misuratore di distanza, stavo per
accingermi a studiare i floating points, ma un utente, mi aveva subito messo in guardia.
In effetti non è assolutamente necessario.
Tutto mi serviva per calcolare in base al tempo di ritorno del suono,e alla sua velocità in aria, la distanza espressa in cm.
Con una moltiplicazione e una divisione (ora non ricordo, mi pare da 24 e 16 bits), ho risolto, e tutto funzionava perfettamente.
Tutto veniva poi stampato su lcd o su hyper terminal.
Ma qui, trovo pazzesco il fatto di dover fare lo stesso procedimento, oppure avere l'ansia che il risultato di un double sia approssimato.
Ok, nel 99,9 % dei casi quell'approssimazione è accettabile, ma nel mio caso assolutamente no!
Non ho ancora letto il tuo link, ma mi domando, se non potevano implementare nel C quel tipo di operazioni float che mi hai linkato.
Se me lo hai indicato, evidentemente, si possono aggirare le approssimazioni...quindi perchè non metterle di standard ?
Ma credo che la risposta sia nel link...evidentemente ci sono impicci, che non posso capire finchè non leggo.
Avatar utente
M_A_W_ 1968
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 856
Iscrizione: venerdì 15 febbraio 2013, 3:57
Desktop: KDE
Distribuzione: SuSE
Sesso: Maschile
Località: Un luogo geometrico
Contatti:

Re: Problema con variabile double[C]

Messaggio da M_A_W_ 1968 »

gila75 [url=http://forum.ubuntu-it.org/viewtopic.php?p=4580609#p4580609][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto: Se me lo hai indicato, evidentemente, si possono aggirare le approssimazioni...quindi perchè non metterle di standard ?
In primo luogo, perché non è qualcosa che si possa affidare ad uno stupido compilatore. Minimizzare gli errori inerenti richiede un livello di comprensione contestuale che una macchina, al momento (e per un bel pezzo ancora, sic stantibus rebus...), non può avere.

Secondariamente, ma non meno importante: perché la schiacciante maggioranza delle piattaforme per le quali esiste un compilatore C non hanno né l'hardware richiesto né tantomeno la necessità di usare il floating point. Ricorda e ricordate sempre che la carta d'identità del core embedded quadratico medio più venduto in assoluto (si parla di decine di miliardi di pezzi all'anno, numeri che fanno impallidire qualsiasi altro possibile mercato di semiconduttori programmabili) è un balocco con datapath a 8 bit, program memory a 14/18 bit, 10/40 MIPS e una quantità di memorie aggregate (PM, data/file register, EEPROM seriali varie...) esprimibile in kib con due sole cifre. Un aggeggio che, nel migliore dei casi, a livello di calcolo aritmetico dispone solo di un moltiplicatore hardware tra interi, operante in uno o due cicli di clock - ma più spesso non ha neppure quello. E solo nella prima decade del nuovo millennio questo tipo di architettura ha sorpassato, seppure di poco, i volumi di vendita del suo più accanito e diretto "concorrente" a 4 bit di datapath.
Ultima modifica di M_A_W_ 1968 il domenica 11 maggio 2014, 13:26, modificato 1 volta in totale.
Sì, un blog ce l'ho perfino io: gli è che mi manca il tempo...

"...in una società che sembra sempre più spaventata dai problemi troppo articolati e che rigetta come un corpo estraneo ogni elemento di complessità, sapremo ancora come utilizzare il parere degli esperti?"
Avatar utente
M_A_W_ 1968
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 856
Iscrizione: venerdì 15 febbraio 2013, 3:57
Desktop: KDE
Distribuzione: SuSE
Sesso: Maschile
Località: Un luogo geometrico
Contatti:

Re: Problema con variabile double[C]

Messaggio da M_A_W_ 1968 »

NIHIL
Sì, un blog ce l'ho perfino io: gli è che mi manca il tempo...

"...in una società che sembra sempre più spaventata dai problemi troppo articolati e che rigetta come un corpo estraneo ogni elemento di complessità, sapremo ancora come utilizzare il parere degli esperti?"
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Problema con variabile double[C]

Messaggio da gila75 »

Avatar utente
M_A_W_ 1968
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 856
Iscrizione: venerdì 15 febbraio 2013, 3:57
Desktop: KDE
Distribuzione: SuSE
Sesso: Maschile
Località: Un luogo geometrico
Contatti:

Re: Problema con variabile double[C]

Messaggio da M_A_W_ 1968 »

In latino, nihil significa "nulla"... in questo caso, indica un post erroneamente duplicato. A quanto pare, in questo forum gli utenti non possono cancellare i propri post, neppure se si trovano temporaneamente al termine di un thread.
Sì, un blog ce l'ho perfino io: gli è che mi manca il tempo...

"...in una società che sembra sempre più spaventata dai problemi troppo articolati e che rigetta come un corpo estraneo ogni elemento di complessità, sapremo ancora come utilizzare il parere degli esperti?"
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Problema con variabile double[C]

Messaggio da gila75 »

ok,grazie...:)
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Problema con variabile double[C]

Messaggio da gila75 »

@ Claudio_F
Si, intendo quello, nota che i coefficienti non devono necessariamente essere potenze di dieci, potresti anche moltiplicare per 2 alla 32, e alla fine l'aggiustamento della virgola non richiederebbe divisioni per 10 ma semplici shift a destra di N bit.
Questo non lo avevo mai pensato sinceramente.

Comunque per ora l'esperimento della particella saltatrice del mio libro, l'ho risolta così :

Codice: Seleziona tutto

#include <string.h>                                       
#include <stdlib.h>
#include <stdio.h>
#define N 4
#define N_S 100

void particella_1 (int p_1[], char storia_p_1[],int rif[]); 
void particella_2 (int p_2[], char storia_p_2[],int rif[]); 
int confronta (char storia_p_1[], char storia_p_2[]); 


int confronta (char storia_p_1[], char storia_p_2[])
{
    int j;
    for (j=0; j<N_S; j++)
    {
        if (storia_p_1[j]!=storia_p_2[j])
        {
            printf ("interrotto a %d\n",j+1);
            break;
        }
    }
    return j;
}






//****************************************************************//
//                   P_1                                        
//****************************************************************//

void particella_1 (int p_1[], char storia_p_1[],int rif [])
{
    
    int i;
    int rip=0;
    int temp;
    int x;
    for (x=0; x<N_S; x++)
        {

            for (i=N-1; i>=0; i--)
            {
                temp=(p_1[i]*2)+rip;

                    if (temp>=10)
                    {
                            rip=1;
                            p_1[i]=(temp-10);
                    }  
                    else
                    {   
                        p_1[i]=temp;
                        rip=0;
                    }
            
                temp=p_1[0];
                p_1[0]=p_1[0]-temp;
            }

            for (i=1; i<N; i++)
            {
                if (p_1[i]>rif[i])
                {
                    storia_p_1[x]='S';
                    break;
                }
            
                if (p_1[i]<rif[i])
                {
                    storia_p_1[x]='D';
                    break;
                }
            }

    } 
    return;
}

//****************************************************************//
//                   P_2                                     
//****************************************************************//
void particella_2 (int p_2[], char storia_p_2[],int rif [])
{
    
    int i;
    int rip=0;
    int temp;
    int x;
    for (x=0; x<N_S; x++)
        {

            for (i=N-1; i>=0; i--)
            {
                temp=(p_2[i]*2)+rip;

                    if (temp>=10)
                    {
                            rip=1;
                            p_2[i]=(temp-10);
                    }  
                    else
                    {   
                        p_2[i]=temp;
                        rip=0;
                    }
            
                temp=p_2[0];
                p_2[0]=p_2[0]-temp;
            }

            for (i=1; i<N; i++)
            {
                if (p_2[i]>rif[i])
                {
                    storia_p_2[x]='S';
                    break;
                }
            
                if (p_2[i]<rif[i])
                {
                    storia_p_2[x]='D';
                    break;
                }
            }

    } 
    return;
}
//********************************************************


int main(void)
{
   
    
    int p_1[N]={0,1,4,2};
    int p_2[N]={0,1,4,1};
    int rif[N]= {0,5,0,0};
    char storia_p_1[N_S]={};
    char storia_p_2[N_S]={};
    int i;
    int res;


    particella_1 (p_1,storia_p_1,rif);
    particella_2 (p_2,storia_p_2,rif);
    
    res= confronta (storia_p_1,storia_p_2);

    printf ("--------------------------p1---------------\n"); 
    for (i=0; i<N_S; i++)
    {
        if (i==res)
            printf ("X");
        printf ("%c",storia_p_1[i]);
    }
        
    printf ("\n");
    printf ("--------------------------p2---------------\n"); 
    for (i=0; i<N_S; i++)
    {
        if (i==res)
            printf ("X");
        printf ("%c",storia_p_2[i]);
    }
    
    
    return 0;
}           
Il metodo che ho escogitato però non fornisce un numero , ma un array di numeri, quindi per stabilire se è maggiore o minore di 0.5, devo comparare ogni singolo
numero nell'array con un altro array che conterrà 0.5.
Grazie a tutti, ora cercherò di capire il link di M_A_W :D
P.S: M_A_W... tu mi distruggi a volte...mi hai messo un mega link, ma da come hai scritto, sembra che il tempo di una sigaretta ed è fatta... in scioltezza dai... :D :muro:
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Problema con variabile double[C]

Messaggio da gila75 »

Lascio aperto il 3d, vorrei discutere dopo aver letto il link proposto da M_A_W.
Una cosa molto strana però:

Nel programma d'esempio (il primo), usando i double, l'errore inizia a 0.72*2=0.440001 (anzichè 0.44).
Facendo un programmino a parte che fa 0.72*2 o 0.72+0.72, il valore è corretto, sempre usando i double :muro:

Magari non è ancora roba per me, ma non mi lascia tranquillo il fatto che ogni x volte, senza sapere il perchè, possa avere questi errori, nemmeno a livello hobbistico.
Si rischia d'impazzire e non capire il motivo.
Io vedendo stranezze non previste, mi sono messo carta e penna e ho trovato l'errore, ma non sempre carta e penna è fattibile!!!

EDIT :(

Non è fattibile per ora decifrare il link...mi limito ad una spiegazione più basilare per ora dei floating points.
Magari più avanti....
Eventualmente, posto le mie perplessità.
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Problema con variabile double[C]

Messaggio da gila75 »

Ho iniziato a leggere il post di M_A_W, e altri un po' più semplici e in italiano.
Lo studio dei floating points, non è così semplice e richiede tempo e fatica. A dire il vero, non so se è cosa per me, ma mi affascina la cosa...quindi :D
Da una prima lettura un po' sommaria ho capito che un numero float o double si compone da
1 bit per il segno (per numeri negativi o positivi).
8 bits per la base
23 bits per la mantissa (che esprimerà la parte decimale). 55 bits per i double

Quindi in totale 1+8+23=32 bits ( se si parla di float), 64 se double.
Andando avanti con la lettura, si capisce il limite intrinseco dei numeri in virgola mobile di rappresentare tutti i numeri decimali. Semplicemente non è possibile, se non con approssimazioni.
Prendiamo per esempio il numero 0.3

la base sarà logicamente 0.
Per calcolare la parte decimale, mi pare di aver capito che si fa:
0.3*2=0.6 (0)
0.6*2=1.2 (1)
0.2*2=0.4 (0)
0.4*2=0.8(0)
0.8*2=1.6(1)
0.6*2=1.2(1)
0.2*2=0.4(0)
0.4*2=0.8(0)

scrivendo in binario avrei :
0.01001100

in questo caso ho usato una mantissa di soli 8 bits, che a conti fatti mi danno questa precisione:
(1/32)+(1/16)+(1/2)=0.03125+0.0625+0.5= 0.59375/2=0.296875

Quindi il margine d'errore= 0.3-0.296875=0.003125 (1.041% d'errore,abbastanza alto direi)

Ho messo,nell'espressione sopra, diviso 2, perchè, non ho ben capito il motivo, ma quando c'è uno zero subito dopo la virgola, il risultato
va diviso per 2 (o shifato a sx di 1 posto).
Mi pare di aver letto qualcosa a riguardo (normalizzazione o cose del genere, ma ci arriverò).
Comunque, se ho ben capito, alcuni numeri, non sono descrivibili in modo preciso, al di la della lunghezza della mantissa.
Diciamo che per una mantissa tendente all'infinito, il margine d'errore tende a zero, ma non lo raggiungerà mai.
Logicamente casi come 0.5, 0.25 danno risultati precisi.
Magari,nel mio caso, il programma che raddoppia ogni volta il numero di partenza 0.33, dopo n cicli, l'errore si accumula e ho risultati inattesi.
Mentre facendolo singolarmente, l'errore è talmente basso che rientra nell'arrotondamento previsto.
Per ora ho letto (anche un po' velocemente) questo, vorrei capire se ciò che ho detto è corretto.
Logicamente tutto il procedimento per mettere il numero binario in memoria, che esprima segno,base e tutto il resto è molto più complesso, e lo devo studiare.
Per ora ho voluto focalizzare un po' l'attenzione solo sul procedimento e capire questo limite che hanno i floating points nel rappresentare i numeri decimali.
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 4 ospiti