Pages: [1] 2 3 4   Go Down
Author Topic: Mi servono 6-7 decimali ma float non va....  (Read 1540 times)
0 Members and 1 Guest are viewing this topic.
Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 517
Posts: 12318
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Il problema è noto, la cifra 2749999.9925 trattata con float diventa 2750000.0000, perché non riesce a gestire più di 7 cifre totali.
Nick Gammon qui ha risolto il problema con la sua lib; il link è proprio all'esempio che farebbe al caso mio, l'ho testato e funziona. Ora iniziano i miei guai, perché speravo di dover semplicemente aggiungere la lib ed uno-due comandi di attivazione e conversione al mio sketch per risolvere, invece mi trovo un casino di roba e non riesco a discernere cosa serve e cosa non mi serve.
La condizione del mio sketch è estremamente semplice: leggo un valore digitale e lo assegno alla variabile "valore", se uso una float ottengo risultati stravaganti, quindi sono costretto ad una unsigned long e "tagliare" i decimali. Se potessi recuperarli ne sarei felice, ho speranza di non dover usare tutti quei comandi, perché mi pare servano alla fine a generare quel cavolo di numero immenso, ma invece temo che quei comandi li dovrò usare al posto dei normali operatori aritmetici, ogni volta che eseguo un calcolo su tali numeri; in effetti ho necessità di fare un paio di divisioni ed un paio di moltiplicazioni per fattori numerici fissi (quindi non altre variabili), tutto qui smiley-confuse
Qualcuno ha mai usato questa lib e può darmi un minimo di dritte, risparmiandomi un a settimana di studio, tempo che non ho e che non so nemmeno se mi basterà, viste le mie "conoscenze"?
Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

ivrea (to)
Offline Offline
Faraday Member
**
Karma: 77
Posts: 4645
miaaao ^-^
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Non l'ho mai usata, ma guardando gli esempi di @gammon, si direbbe che gestisce lui con dei puntatori a zone di memoria che allocherà dinamicamente questi numeri big.

primo dichiara quanti digit usare (e mi pare poteva usare byte invece di int), nel tuo caso 4 cifre decimali
Code:
#include "BigNumber.h"
static int DIGITS=4;

Poi dichiara le variabili di tipo bc_num e li inizializza a NULL, perciò presumo siano puntatori.
Code:
bc_num a=NULL, b = NULL, c = NULL;
Ma sembra che puoi anche dichiarate un bc_num x("123"); oppure bc_num y(123);   ma solo int in questo caso

Per inizializzare passa da stringa:
Code:
bc_str2num(&a, "42",DIGITS);
bc_str2num(&b, "18254546", DIGITS);
e per i calcoli usa solo sue funzioni che probabilmente sono le uniche che conoscono che struttura c'e' dietro a quei pointer.
Code:
bc_multiply(a,b,&c,DIGITS);
Nella libreria ultima versione vedo che ha anche creato l'overload per le operazioni più comuni tra due BignNumber, ovvero   c=a*b;   o altre operazioni +-*/%

Ha anche fatto overload dei confronti perciò puoi fare
if(a>=b)   dove
Una volta che le variabili big non gli servono più si ricorda di liberare la memoria:
Code:
bc_free_num (&b);a e b sono numeri big

bc_free_num (&c);


EDIT: nella ultima versione della libreria ha messo un pò di esempi (pde invece di ino e sono un pò diversi dagli esempi del link che hai postato). La libreria ora deriva da Printable e perciò puoi fare direttamente   Serial.printl(c);   dove c è un bignumber.
L'ha migliorata parecchio.
Code:
// BigNumber test: multiplication
#include "BigNumber.h"

void setup ()
{ Serial.begin (115200);
  Serial.println ();
  BigNumber::begin ();  // initialize library
  BigNumber::setScale (5);
  // test multiplication  
  BigNumber a = "564328376.33";
  BigNumber b = "18254546.22";
  BigNumber c = a + b;
  Serial.println (c);
}  // end of setup

void loop () { }

Se però usi cifre che assegni a dei bc, devono essere int, questo non mi funziona, sembra che b lo consideri troncandolo a int:
Code:
BigNumber a = "564328376";
BigNumber b =  111111111.22;
BigNumber c = a + b;
Qui se devi passargli un float:
http://forum.arduino.cc/index.php?topic=85692.msg1127105#msg1127105

E mi sembra importante leggere le note al fondo qui e la funzione "setScale" (impossibile fare un riassunto):
http://www.gammon.com.au/forum/?id=11519
« Last Edit: July 05, 2013, 02:01:15 pm by nid69ita » Logged

my name is IGOR, not AIGOR

Selvazzano Dentro - Padova
Offline Offline
Edison Member
*
Karma: 37
Posts: 1302
"Chi sa fa, chi non sa insegna"
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao Michele.

Ho letto che la DUE gestisce variabili double "vere" a 8 byte e questa sarebbe la soluzione al tuo problema.

Vuoi vedere che tra un po' anche la UNO e la MEGA avranno le variabili di questo tipo?
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Vuoi vedere che tra un po' anche la UNO e la MEGA avranno le variabili di questo tipo?
No, i float a 4 byte sono una limitazione dell'implementazione del compilatore gcc-avr per le mcu ad 8 bit.
Logged


Selvazzano Dentro - Padova
Offline Offline
Edison Member
*
Karma: 37
Posts: 1302
"Chi sa fa, chi non sa insegna"
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Leo, conosci le motivazioni tecniche di una simile limitazione?
Logged

BZ (I)
Offline Offline
Brattain Member
*****
Karma: 251
Posts: 21254
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Leo, conosci le motivazioni tecniche di una simile limitazione?
La potenza di calcolo dei controller a 8 Bit.
Ciao Uwe
Logged

Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 517
Posts: 12318
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

karma Nid, nel doppio senso del termine smiley-lol smiley-lol
Mi pare che l'ultima parte del tuo intervento mi possa risolvere abbastanza rapidamente ogni problema, domattina mi metto a fare prove, quindi stay tuned perché certamente avrò bisogno...intando io visualizzo su LCD, ma vediamo una cosa per volta.
Un solo chiarimento: io ho scaricato la lib del link del primo post, tu parli di versioni diverse, è perché ti sei letto l'intero Topic (a proposito, un grosso grazie a Leo per la segnalazione smiley) o ci sono link differenti? qual è quello più recente?
Grazie mille!
Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

ivrea (to)
Offline Offline
Faraday Member
**
Karma: 77
Posts: 4645
miaaao ^-^
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Io ho scaricato la libreria da link che tu hai messo. Poi sempre a quel link ho visto che gli esempi sono un pò diversi rispetto a quelli della libreria. Secondo me a quel link c'è poi il link al sito di @gammon che è sempre l'ultima versione.
Infatti nel link che hai postato a pagina 3 dice che ha migliorato la libreria rendendola "stampabile" con la print() e println()

La difficoltà della libreria secondo me è assegnare a questi numeri un valore.
Lo puoi fare o attraverso una stringa o solo da int, no da un float direttamente:
Code:
bc_num a=NULL,b=NULL;
a="12345.678";  // ok
b=32767;          // ok
b=111111111.2222;   // no, troncato a int

Nella setup() dovrai usare setScale(4)  visto che vuoi 4 decimali
Code:
BigNumber::begin ();  // initialize library  
BigNumber::setScale (4);

La libreria si appoggia ad una ulteriore libreria allegata che ha le primitive tipo un bc_str2num() e bc_int2num()
Non c'e' un bc_float2num() oppure bc_long2num() purtroppo
Si potrebbe chiedere a @Gammon se potrebbe inserirla.
« Last Edit: July 05, 2013, 03:41:10 pm by nid69ita » Logged

my name is IGOR, not AIGOR

Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 517
Posts: 12318
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

domattina mi metto a fare qualche piccola prova, e leggerò la tua prossima risposta, ora sto dormendo sulla tastiera smiley-sleep smiley-sleep smiley-sleep a questa domanda: nell'esempio che ho linkato lui alla fine ottiene un numero con un intero e 103 decimali, come ha fatto?

Inoltre ora a me viene il grandioso dubbio.... attualmente leggo un valore frutto di una serie di calcoli con timer e roba varia (una ulteriore lib, ovviamente), ma se il limite è dato dagli 8 bit, il mio valore iniziale 2.749.999,25 Hz REALE, applicato al micro, lo vedrò mai lato software? cioè se alla fine dei calcoli della prima lib io non riesco in alcun modo a preservare questo valore ed i suoi decimali, come faccio a ricostruire quello originale, da cui esso deriva?
Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

ivrea (to)
Offline Offline
Faraday Member
**
Karma: 77
Posts: 4645
miaaao ^-^
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

domattina mi metto a fare qualche piccola prova, e leggerò la tua prossima risposta, ora sto dormendo sulla tastiera smiley-sleep smiley-sleep smiley-sleep a questa domanda: nell'esempio che ho linkato lui alla fine ottiene un numero con un intero e 103 decimali, come ha fatto?

Inoltre ora a me viene il grandioso dubbio.... attualmente leggo un valore frutto di una serie di calcoli con timer e roba varia (una ulteriore lib, ovviamente), ma se il limite è dato dagli 8 bit, il mio valore iniziale 2.749.999,25 Hz REALE, applicato al micro, lo vedrò mai lato software? cioè se alla fine dei calcoli della prima lib io non riesco in alcun modo a preservare questo valore ed i suoi decimali, come faccio a ricostruire quello originale, da cui esso deriva?
1. usa questa -> BigNumber::setScale (103);
mi sembra che la sua libreria internamente memorizza come stringa (vettore di char)

2. non credo riuscirai se non passi a fare i calcoli con la BigNumber
Logged

my name is IGOR, not AIGOR

0
Offline Offline
Shannon Member
****
Karma: 130
Posts: 10448
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

menniti, domanda stupida stupida.. se ti servono 6/7 cifre decimali, non puoi memorizzare i valori, anzichè come 10^0, come 10^-6?

puoi usare degli uint64_t per evere spazio a sufficienza (sono dei long long  smiley-mr-green), certo devi fare attenzione alla matematica.

la libreria di nick l'ho usata con successo recentemente ma ti ciuccia la RAM che è un piacere, se vuoi l'esempio funzionante (us anche l'add on di un altro tipo per seno coseno etcc) segui il link in firma, tra gli arduinoSketch cerca il "testGps" e trovi tutto

leggi qui la mia avventura:
http://forum.arduino.cc/index.php?topic=106614.msg799858#msg799858
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Selvazzano Dentro - Padova
Offline Offline
Edison Member
*
Karma: 37
Posts: 1302
"Chi sa fa, chi non sa insegna"
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Lesto, per favore, chiariscimi questo concetto.

Ho provato a dichiarare una variabile long long, ma l'IDE 1.0.5 non me la riconosce:

long long Prova = 12345678901;

error: integer constant is too large for 'long' type

Ma se faccio così il compilatore non da errore:
long long Prova = 12345678901ULL;
« Last Edit: July 05, 2013, 11:09:25 pm by cyberhs » Logged

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 120
Posts: 9165
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ma se faccio così il compilatore non da errore:
long long Prova = 12345678901ULL;

Perché serve l'opzione "-mint8" ad avrgcc per poter utilizzare il long long int, purtroppo non è possibile fornirla tramite ide di Arduino, si può fare solo con AvrStudio, o direttamente da riga di comando, ovvero dall'ide di Arduino non è possibile utilizzare gli interi a 64 bit anche se supportati dalle avrlibc.
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Allora mi sa che dovete aggiornare la vostra toolchain.
Io con la toolchain Atmel compilo senza errori:


* longlong.jpg (72.62 KB, 438x495 - viewed 14 times.)
Logged


ivrea (to)
Offline Offline
Faraday Member
**
Karma: 77
Posts: 4645
miaaao ^-^
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@leo però tu usi la 1.0.5+ (la nightly build). Magari è quella che cambia ?

EDIT: a me questo lo compila senza problemi con ide 1.0.5 e non ho cambiato la toolchain (ho però installato anche AvrStudio 6.1 ma non penso influenzi l'IDE !?!)
Code:
long long x=0;
void setup() {}

void loop()
{ x++;
}

Come detto da @cyberhs da problemi con una costante senza qualificatore, ma mi sembra corretto. Comunque i long long funzionano con il semplice 1.0.5 senza cambiare toolchain. C'e' solo quell'appunto sull'inizializzazione da costante.
« Last Edit: July 06, 2013, 03:30:00 am by nid69ita » Logged

my name is IGOR, not AIGOR

Pages: [1] 2 3 4   Go Up
Jump to: