Aritmetica a punto fisso su microcontrollori


12

Spesso usiamo i microcontrollori per fare le cose nei nostri robot, ma dobbiamo fare dei calcoli in decimali. L'uso di variabili in virgola mobile è molto lento, poiché viene automaticamente inclusa una libreria software in virgola mobile (a meno che non si disponga di un microcontrollore di fascia alta). Pertanto, generalmente utilizziamo l'aritmetica a punto fisso.

Ogni volta che lo faccio, uso solo un numero intero e ricordo dove si trova il decimale. Tuttavia, è necessario assicurarsi che tutto sia coerente, soprattutto quando i calcoli coinvolgono variabili in cui il punto decimale si trova in una posizione diversa.

Ho implementato una funzione atan2 a punto fisso, ma poiché stavo cercando di comprimere ogni ultima goccia di precisione limitata (16 bit), spesso cambiavo la definizione di dove si trova il punto decimale e cambiava mentre lo modificavo. Inoltre, avrei alcune costanti, come una tabella di quasi ricerca, che a loro volta hanno un punto decimale implicito da qualche parte.

Voglio sapere se esiste un modo migliore. Esiste una libreria, o un insieme di macro, che può semplificare l'uso di variabili a virgola fissa, semplificando la moltiplicazione e la divisione tra variabili miste e consentendo la dichiarazione di numeri decimali o espressioni costanti, ma convertendo automaticamente la rappresentazione in virgola fissa desiderata durante la compilazione tempo?


1
Penso che in realtà sia meglio per StackOverflow poiché la soluzione è generica e non ha molto a che fare con la robotica.
Shahbaz,

1
@Jakob - Nota che entrambe queste domande sono state chiuse in quanto non costruttive.
Mark Booth

1
Questo è il genere di cose che renderebbe C ++ molto utile per i sistemi embedded. I modelli genererebbero automaticamente il codice corretto e ottimale.
Rocketmagnet,

1
Posso dare un'occhiata alla tua funzione atan? Sto cercando di affrontare il problema della conversione da virgola mobile a punto fisso nella mia ricerca accademica e sarei felice di prenderlo.
Joe Hass,

1
Parti @ronalchn di Arduino (un micro AVR) lingua sono implementate in C ++. C'è anche una libreria C ++ AVR . E questa discussione su quali compilatori usare.
embedded.kyle

Risposte:


7

Sarebbe bello se potessimo dire al compilatore l'intervallo e la precisione di ciascuna variabile di input a punto fisso (forse non due che hanno il punto radix nella stessa posizione), e utilizzerebbe automagicamente - al momento della compilazione - l'intervallo corretto e operazioni di precisione e riscalamento per i valori intermedi e i valori finali in una serie di calcoli. Ho sentito voci che potrebbe essere possibile farlo nel linguaggio di programmazione Ada o nei modelli C ++.

Purtroppo, il più vicino che ho visto sono le librerie aritmetiche a punto fisso che richiedono a te, il programmatore, di scegliere manualmente la rappresentazione corretta e verificare manualmente che ogni operazione mantenga un intervallo e una precisione adeguati. A volte facilitano la moltiplicazione e la divisione tra variabili miste. Ad esempio:


È quasi certamente possibile farlo utilizzando modelli C ++.
Rocketmagnet,

In realtà sto lavorando a qualcosa come il tuo commento "sarebbe bello se ...". È un plugin per gcc che converte il codice C in virgola mobile in punto fisso, ottimizzando tutte le posizioni dei punti binari lungo il percorso. Ho un documento inviato a un giornale ACM e un altro in preparazione. Se hai il codice C per la funzione atan, sarei felice di provarlo ... Potrei restituirti il ​​codice C che usa variabili intere e fa tutte le cose a virgola fissa.
Joe Hass,

+1 per una risposta molto più completa della mia. Ho modificato il mio collegamento per includere un collegamento a un luogo per richiedere il codice sorgente per rispondere al commento di Mark Booth. Potresti voler aggiornare anche il tuo link. Lo farei da solo, ma una modifica suggerita è in coda e mi sta bloccando.
embedded.kyle

1
@Rocketmagnet È certamente possibile implementare punti fissi usando i template, vedi FixedPoints (dichiarazione di non responsabilità: ho scritto questo ed è ancora molto "giovane").
Pharap,

il link gcc "a" è rotto
Lesto

2

Ho usato la libreria IQMath di TI per implementare il virgola mobile virtuale sui loro DSP in virgola fissa.

La libreria IQmath TMS320C28x di Texas Instruments è una raccolta di funzioni matematiche altamente ottimizzate e di alta precisione per i programmatori C / C ++ per il porting continuo di un algoritmo a virgola mobile in codice a virgola fissa su dispositivi TMS320C28x. Queste routine sono generalmente utilizzate in applicazioni real-time ad alta intensità computazionale in cui la velocità di esecuzione ottimale e l'elevata precisione sono fondamentali. Usando queste routine è possibile raggiungere velocità di esecuzione molto più veloci di un codice equivalente scritto nel linguaggio ANSI C. Inoltre, fornendo funzioni di alta precisione pronte all'uso, la libreria TI IQmath può ridurre significativamente i tempi di sviluppo delle applicazioni DSP.

Che utilizza alcune cose specifiche di TI ma ho anche usato quel codice come base per implementare la matematica a virgola mobile virtuale su altri microcontrollori. Ci vuole un po 'di lavoro per port ma è molto più facile che ricominciare da zero.


@downvoter Ti interessa commentare cosa c'era di sbagliato nella mia risposta?
embedded.kyle,

+1: questa libreria è migliore di quella che sta usando ora ("usa solo un numero intero"). Non fa tutto ciò che la domanda originale ha chiesto, ma penso che una risposta come questa (utile, ma non una soluzione completa) non meriti un downvote - a meno che non esista effettivamente una soluzione completa (che dubito in questo caso ).
David Cary,

Mi sembra che una risposta che sia specifica per una singola gamma di dispositivi ed è gratuita solo come nella birra piuttosto che nella parola, è di scarsa utilità per i futuri visitatori.
Mark Booth

@MarkBooth Ho cambiato il collegamento dalla libreria C28x alla libreria C64x. Se segui quel link, puoi richiedere il codice sorgente. Hai bisogno di una società o di un'e-mail universitaria per accedere. Ancora libero come nella birra e nella parola. Devi solo alzare la mano e aspettare di essere chiamato prima di poter parlare. Un po 'fastidioso, ma una volta che hai il codice sorgente, può essere adattato a qualsiasi processore ti piaccia.
embedded.kyle

Grazie al codice sorgente @ embedded.kyle è decisamente meglio del solo binario, ma comunque di scarso uso generale se la licenza consente di utilizzarlo solo in modi limitati. Secondo la pagina delle biblioteche del software C6x tale fonte è rilasciata solo sotto licenza commerciale TI , che quasi certamente non è gratuita come nel parlato .
Mark Booth

1

Esistono diverse implementazioni (nessuna libreria di cui sono immediatamente a conoscenza) di Binary Scaling (aka B-scaling)

In questo, tieni una nota mentale (o meglio, documenta il codice ...) di dove si trova il punto decimale, usando i turni per spostare il punto decimale su o giù.

Ho usato il ridimensionamento B in assemblatore su progetti di difesa, anche sulle CPU più piccole, quindi posso garantire la sua idoneità per qualsiasi altra cosa ...


Probabilmente qualcosa del genere, ma non l'ho mai visto definito b-scaling. Lo considero un punto fisso - il decimale non è mai mobile perché anche se il punto decimale potrebbe cambiare nel corso dei calcoli, ogni variabile ha sempre il punto decimale fissato in una posizione particolare
ronalchn

0

Se usi un numero intero per ricordare dove si trova il "punto", usano un tipo di aritmetica in virgola mobile. Punto fisso, ha davvero un punto fisso .

atancosππ

Ciò dipende dalla gamma di valori richiesti dall'applicazione, ma è possibile che si desideri spostare completamente in una rappresentazione in virgola fissa. Cioè, ad esempio, invece di mantenere un numero come questo:

struct num
{
    uint16_t number;
    uint16_t decimal_point;
};

dove numberè il numero intero e decimal_pointdice dove si trova il punto decimale, è possibile memorizzarlo in questo modo:

struct num
{
    uint16_t integer;
    uint16_t fraction;
};

dove si trova l'intero numero integer.fraction, che ha lo stesso utilizzo della memoria, un intervallo di valori più elevato e in generale più semplice da usare.


La memorizzazione effettiva del punto decimale lo rende più simile a un punto mobile. Normalmente il punto decimale viene definito al momento della compilazione e si cambia tra rappresentazione a seconda dell'operazione.
Jakob,

Non intendo ricordare come memorizzato in una variabile, intendo ricordare come in Ricordo come interpretare il risultato (sapendo dove si trova il punto decimale)
ronalchn,

@ronalchn, vedo. Intendi qualcosa di simile a con #define, giusto? Pensavo che lo avessi effettivamente archiviato e può variare in base a quanto è grande o piccolo il tuo numero.
Shahbaz,

@ronalchn - stai pensando al ridimensionamento B? (vedi la mia risposta)
Andrew
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.