2015-11-17 14 views
5

consideri il seguente semplice divisione:Controllo precisione divisione

A=8.868; 
A/0.1 
ans = 
    88.679999999999993 

Ciò provoca un piccolo errore, a causa di precisione in virgola mobile. C'è un modo per evitare che ciò accada? Fondamentalmente tutto quello che sto facendo è spostare la virgola di una posizione, pur non essendo vicino al numero massimo di cifre consentite in MATLAB.

mi piacerebbe ottenere un risultato come:

A/0.1 
ans = 
    88.68 

dove zeri finali sono di alcuna preoccupazione, fintanto che sono a zero, e non contiene un numero al 14 cifre o giù di lì.

È interessante notare che questo problema schiocca anche quando l'arrotondamento a N cifre:

R = (randi([8659 49847],[1e3 1]))/1e3; 
xmin = min(R); 
el = 0.1; 
step = 1/el; 
tmp1=xmin/el; 
tmp2=round(tmp1); 
tmp3=round(tmp2*el,3); 

tmp3 = 
    8.699999999999999 
+0

Solo per curiosità: perché in questo modo? perché non moltiplicare per 10? –

+0

@AnderBiguri perché è nel mio caso la mia dimensione della griglia in centimetri, il che significa che può anche essere ad es. 0,25, 0,12 o qualsiasi cosa il cliente desideri. – Adriaan

+0

@AnderBiguri 'A * 10' è anche impreciso in questo caso ... – Dan

risposta

6

Utilizzando la matematica simbolica, è possibile ottenere risultati precisi:

x=sym('8.868')/sym('.1') 
+1

Come funziona in termini di velocità? Poiché ho circa 800 punti di dati, la velocità è un problema importante. – Adriaan

+2

La matematica simbolica è molto lenta, probabilmente impossibile per tali dimensioni di dati. – Daniel

5

È sempre possibile utilizzare fixed point aritmetica in cui la pendenza è un multiplo di 10. Non avrai alcuna inesattezza quando moltiplichi/dividi per dieci. In Matlab, è possibile utilizzare Fixed Point Toolbox

Edit: seguito il commento - sembra che è possibile impostare la pendenza di essere 0,05.

+0

Come ho sottolineato in [il mio commento] (http://stackoverflow.com/questions/33754807/controlling-division-precision#comment55277249_33754807) la pendenza non sarà sempre un multiplo di 10. – Adriaan

+0

@Adriaan, puoi trovare il multiplo comune di ciò che può essere la pendenza? Altrimenti, puoi sempre usare matematica di precisione infinita. –

+0

I miei dati sono dati millimetrici di precisione, cioè tre cifre, che voglio inserire nella griglia di X cm, dove X è determinato dalla risoluzione richiesta dal cliente. Solitamente X è 0,1, 0,25 o 0,5 m, quindi è ciò che i dati devono essere arrotondati a. – Adriaan

3

È possibile rappresentare i numeri come frazioni di numeri interi. Finché non si converte a stare a galla, non si perde di precisione:

A = 8.868; 
div = 0.1; 
[N1,D1] = rat(A); 
[N2,D2] = rat(div); 
% divide A by div: 
N = N1 * D2; 
D = N2 * D1; 

Naturalmente i numeri potrebbero non essere precisi per cominciare, come detto in altre risposte/commenti. La conversione in frazioni può anche introdurre un'approssimazione, ma ciò dipende dai numeri con cui si ha a che fare e dal parametro tol a rat.

+1

Questa idea è implementata [qui] (http://stackoverflow.com/a/20873563/2732801) – Daniel

4

Questa risposta è pubblicata solo per completezza nel mio caso.


ho aggirato la questione un po 'nel mio caso utilizzando la terza uscita di unique:

el = 0.25; 
A = (randi([7364 84635],[1e4 1]))/1e3; 
B = A/el; 
C = round(B); 
D = C*el; 
[tmp1,tmp2,tmp3] = unique(D); 
E = tmp1(tmp3,:); 
all(E==D) 
ans = 
    1 

che fa correttamente il binning. Quindi, anche se i punti centrali potrebbero non essere esatti con precisione infinita, sono compresi almeno tra 10 cifre, che è più della precisione a 3 cifre dei miei dati originali.