Main Content

Aritmetica in virgola fissa

Addizione e sottrazione

L’addizione di numeri in virgola fissa richiede che i punti binari degli addendi siano allineati. L’addizione viene quindi eseguita utilizzando l’aritmetica binaria in modo che non venga utilizzato nessun numero diverso da 0 o 1.

Ad esempio, si consideri di sommare 010010,1 (18,5) a 0110,110 (6,75):

010010.1+0110.110¯011001.010(18.5)(6.75)(25.25)

La sottrazione in virgola fissa è equivalente all’addizione, utilizzando il valore in complemento a due per qualsiasi valore negativo. Nella sottrazione, gli addendi devono essere estesi di segno affinché la loro lunghezza corrisponda. Ad esempio, si consideri di sottrarre 0110,110 (6,75) da 010010,1 (18,5):

010010.1000110.110¯(18.5)(6.75)

Il fimath globale predefinito ha un valore di 1 (vero) per la proprietà CastBeforeSum. Questo converte gli addendi al tipo di dati somma prima dell'addizione. Pertanto, non è necessario alcun ulteriore spostamento durante l’addizione per allineare i punti binari.

Se CastBeforeSum ha un valore di 0 (falso), gli addendi vengono aggiunti mantenendo la massima precisione. Dopo l’addizione la somma viene quindi quantizzata.

Moltiplicazione

La moltiplicazione di numeri in virgola fissa in complemento a due è direttamente analoga alla normale moltiplicazione decimale, con l'eccezione che i risultati intermedi devono essere estesi di segno affinché i lati sinistri siano allineati prima di sommarli.

Ad esempio, si consideri di moltiplicare 10.11 (-1.25) con 011 (3):

Tipi di dati di moltiplicazione

I diagrammi seguenti mostrano i tipi di dati utilizzati per la moltiplicazione in virgola fissa utilizzando il software Fixed-Point Designer™. I diagrammi illustrano le differenze tra i tipi di dati utilizzati per la moltiplicazione reale-reale, complesso-reale e complesso-complesso.

Moltiplicazione reale-reale.  Il diagramma seguente mostra i tipi di dati utilizzati dal toolbox nella moltiplicazione di due numeri reali. Il software restituisce l’output di questa operazione nel tipo di dati prodotto, regolato dalla proprietà ProductMode dell’oggetto fimath.

Moltiplicazione reale-complesso.  Il diagramma seguente mostra i tipi di dati utilizzati dal toolbox nella moltiplicazione di un numero reale con un numero complesso in virgola fissa. Le moltiplicazioni reale-complesso e complesso-reale sono equivalenti. Il software restituisce l’output di questa operazione nel tipo di dati prodotto, regolato dalla proprietà ProductMode dell’oggetto fimath:

Moltiplicazione complesso-complesso.  Il diagramma seguente mostra la moltiplicazione di due numeri complessi in virgola fissa. Si noti che il software restituisce l’output di questa operazione nel tipo di dati somma, regolato dalla proprietà SumMode dell’oggetto fimath. Il tipo di dati prodotto intermedio è determinato dalla proprietà ProductMode dell’oggetto fimath.

Quando la proprietà CastBeforeSum dell’oggetto fimath è true, nel diagramma precedente le conversioni di tipo dei dati somma si trovano dopo i moltiplicatori. Nel codice C questo è equivalente a

acc=ac;
acc-=bd;

per il sottrattore e a

acc=ad;
acc+=bc;

per l’addizionatore, dove acc è l’accumulatore. Quando la proprietà CastBeforeSum è false, le conversioni non sono presenti e i dati rimangono del tipo di dati prodotto prima delle operazioni di sottrazione e addizione.

Moltiplicazione con fimath

Nell’esempio seguente lasciare

F = fimath('ProductMode','FullPrecision',...
'SumMode','FullPrecision');
T1 = numerictype('WordLength',24,'FractionLength',20);
T2 = numerictype('WordLength',16,'FractionLength',10);

Reale*Reale.  Si noti che la lunghezza della parola e la lunghezza della frazione del risultato z sono rispettivamente uguali alla somma delle lunghezze delle parole e delle lunghezze delle frazioni dei moltiplicandi. Questo è dovuto al fatto che le proprietà fimath SumMode e ProductMode sono impostate su FullPrecision:

P = fipref;
P.FimathDisplay = 'none';
x = fi(5, T1, F) 

x =
 
     5


          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 24
        FractionLength: 20

y = fi(10, T2, F) 

y =
 
    10


          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 16
        FractionLength: 10

z = x*y 

z =
 
    50


          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 40
        FractionLength: 30

Reale*Complesso.  Si noti che la lunghezza della parola e la lunghezza della frazione del risultato z sono rispettivamente uguali alla somma delle lunghezze delle parole e delle lunghezze delle frazioni dei moltiplicandi. Questo è dovuto al fatto che le proprietà fimath SumMode e ProductMode sono impostate su FullPrecision:

x = fi(5,T1,F) 

x =
 
     5


          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 24
        FractionLength: 20
 
y = fi(10+2i,T2,F) 

y =
 
  10.0000 + 2.0000i


          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 16
        FractionLength: 10
 
z = x*y 

z =
 
  50.0000 +10.0000i


          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 40
        FractionLength: 30

Complesso*Complesso.  La moltiplicazione complesso-complesso comporta sia un’addizione sia una moltiplicazione; quindi, la lunghezza della parola del risultato di massima precisione ha un bit in più rispetto alla somma delle lunghezze delle parole dei moltiplicandi:

x = fi(5+6i,T1,F) 

x =
 
   5.0000 + 6.0000i


          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 24
        FractionLength: 20
 
y = fi(10+2i,T2,F) 

y =
 
  10.0000 + 2.0000i


          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 16
        FractionLength: 10
 
z = x*y 

z =
 
  38.0000 +70.0000i


          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 41
        FractionLength: 30

Aritmetica modulo

La matematica binaria si basa sull’aritmetica modulo. L’aritmetica modulo utilizza esclusivamente un insieme finito di numeri, avvolgendo, in tale insieme, i risultati di qualsiasi calcolo che non rientrano nell’insieme specificato.

Ad esempio, il comune orologio utilizza l’aritmetica modulo 12. In questo sistema, i numeri possono essere solo da 1 a 12. Quindi, nel sistema “orologio” 9 più 9 è uguale a 6. Tale concetto è più semplice se viene visualizzato come un cerchio numerico:

Allo stesso modo, la matematica binaria può utilizzare solo i numeri 0 e 1 e tutti i risultati aritmetici che non rientrano in questo intervallo vengono avvolti "intorno al cerchio" su 0 o 1.

Complemento a due

Il complemento a due è un modo per interpretare un numero binario. Nel complemento a due, i numeri positivi iniziano sempre con 0 e i numeri negativi iniziano sempre con 1. Se il bit iniziale di un numero in complemento a due è 0, il valore si ottiene calcolando il valore binario standard del numero. Se il bit iniziale di un numero in complemento a due è 1, il valore si ottiene assumendo che il bit all’estremità sinistra sia negativo e poi si calcola il valore binario del numero. Ad esempio,

01=(0+20)=111=((21)+(20))=(2+1)=1

Per calcolare il negativo di un numero binario usando il complemento a due:

  1. Prendere il complemento a uno o “capovolgere i bit”.

  2. Aggiungere una 2^(-FL) utilizzando la matematica binaria, dove FL è la lunghezza della frazione.

  3. Scartare tutti i bit trasportati che superano la lunghezza della parola originale.

Ad esempio, si supponga di prendere il negativo di 11010 (-6). Per prima cosa, prendere il complemento a uno del numero o capovolgere i bit:

1101000101

Successivamente, aggiungere un 1 avvolgendo tutti i numeri su 0 o su 1:

00101+1¯00110(6)

Conversione

L’oggetto fimath consente di specificare il tipo di dati e il ridimensionamento di somme e prodotti intermedi con le proprietà SumMode e ProductMode. È importante considerare le ramificazioni di ogni conversione quando si impostano le proprietà SumMode e ProductMode. A seconda dei tipi di dati selezionati, potrebbero verificarsi degli overflow e/o degli arrotondamenti. I due esempi seguenti mostrano dei casi in cui possono verificarsi overflow e arrotondamenti.

Nota

Per ulteriori esempi di conversione di tipo, vedere Cast fi Objects.

Conversione da un tipo di dati più corto a un tipo di dati più lungo

Si consideri la conversione di un numero diverso da zero, rappresentato da un tipo di dati a 4 bit con due bit frazionari, in un tipo di dati a 8 bit con sette bit frazionari:

Come mostrato nel diagramma, i bit sorgente sono spostati in alto affinché il punto binario corrisponda alla posizione del punto binario di destinazione. Il bit sorgente più alto non rientra, quindi potrebbe verificarsi un overflow o il risultato può saturare o essere avvolto. I bit vuoti all’estremità inferiore del tipo di dati di destinazione sono riempiti con 0 o con 1:

  • Se non si verifica un overflow, i bit vuoti sono riempiti con 0.

  • Se si verifica un avvolgimento, i bit vuoti sono riempiti con 0.

  • Se si verifica una saturazione:

    • I bit vuoti di un numero positivo sono riempiti con 1.

    • I bit vuoti di un numero negativo sono riempiti con 0.

Come si è potuto constatare, un overflow può comunque verificarsi anche con la conversione da un tipo di dati più corto a un tipo di dati più lungo. Questo può accadere quando la lunghezza dell’intero del tipo di dati sorgente (in questo caso due) è maggiore della lunghezza dell’intero del tipo di dati di destinazione (in questo caso uno). Allo stesso modo, l’arrotondamento potrebbe essere necessario anche quando si esegue una conversione da un tipo di dati più corto a un tipo di dati più lungo, nel caso in cui il tipo di dati di destinazione e il ridimensionamento abbiano meno bit frazionari rispetto alla sorgente.

Conversione da un tipo di dati più lungo a un tipo di dati più corto

Si consideri la conversione di un numero diverso da zero, rappresentato da un tipo di dati a 8 bit con sette bit frazionari, in un tipo di dati a 4 bit con due bit frazionari:

Come mostrato nel diagramma, i bit sorgente sono spostati in basso affinché il punto binario corrisponda alla posizione del punto binario di destinazione. Non esiste alcun valore per il bit sorgente più alto, quindi viene utilizzata l’estensione di segno per riempire la porzione dell’intero del tipo di dati di destinazione. L’estensione di segno è l’aggiunta di bit il cui valore corrisponde al valore del bit più significativo all’estremità superiore di un numero in complemento a due; l’estensione del segno non modifica il valore del numero binario. I cinque bit inferiori della sorgente non rientrano nella lunghezza della frazione di destinazione. Pertanto, la precisione può andare persa poiché il risultato viene arrotondato.

In questo caso, anche se la conversione è da un tipo di dati più lungo a un tipo di dati più corto, vengono mantenuti tutti i bit interi. Al contrario, la massima precisione può essere mantenuta anche quando si effettua una conversione in un tipo di dati più corto, purché la lunghezza della frazione del tipo di dati di destinazione sia uguale o superiore alla lunghezza della frazione del tipo di dati sorgente. In tal caso, tuttavia, i bit all’estremità superiore del risultato sono persi e può verificarsi un overflow.

Il caso peggiore si verifica quando sia la lunghezza dell’intero sia la lunghezza della frazione del tipo di dati di destinazione sono inferiori alle lunghezze del tipo di dati sorgente e del ridimensionamento. In tal caso, può verificarsi sia un overflow sia una perdita di precisione.