(Completamento) Esercitazione per comprendere gli errori di virgola mobile IEEE

Dichiarazione di non responsabilità per contenuto KB ritirato

Il contenuto di questo articolo è riferito a prodotti per cui Microsoft non offre più il supporto. Questo articolo viene pertanto offerto "così com'è" e non sarà più aggiornato.

Riepilogo

Le operazioni matematiche in virgola mobile sono un argomento complesso che confuses molti programmatori. Nell'esercitazione seguente dovrebbe aiutare a riconoscere situazioni di programmazione in cui sono che si verifichino errori di virgola mobile e come evitarli. Dovrebbe consente inoltre di riconoscere i casi che sono causati da limitazioni inerenti matematica a virgola mobile anziché bug del compilatore effettivo.

Ulteriori informazioni

Sistemi di numerazione decimale e binario

In genere, è il conteggio di operazioni in base 10. La base è completamente arbitraria. L'unico motivo che le persone siano state utilizzate tradizionalmente base 10 è 10 dita, che abbia reso pratici strumenti di conteggio.


Il numero di 532.25 in formato decimale (base 10) indica quanto segue:

   (5 * 10^2) + (3 * 10^1) + (2 * 10^0) + (2 * 10^-1) + (5 * 10^-2)
500 + 30 + 2 + 2/10 + 5/100
_________
= 532.25


Nel sistema numerico binario (base 2), ogni colonna rappresenta una potenza di 2 anziché 10. Ad esempio, il numero 101.01 indica quanto segue:

   (1 * 2^2) + (0 * 2^1) + (1 * 2^0) + (0 * 2^-1) + (1 * 2^-2)
4 + 0 + 1 + 0 + 1/4
_________
= 5.25 Decimal


Come valori interi sono rappresentati nei PC

Poiché non esiste alcuna parte frazionaria di un numero intero, la rappresentazione del computer è molto più semplice rispetto ai valori a virgola mobile. Normale interi personal computer (PC) sono di 2 byte (16 bit) long con il bit più significativo che indica il segno. Long integer sono lunghi 4 byte. I valori positivi sono semplici numeri binari. Per esempio:

    1 Decimal = 1 Binary
2 Decimal = 10 Binary
22 Decimal = 10110 Binary, etc.


Tuttavia, numeri interi negativi sono rappresentati utilizzando delle due regime complementare. Per ottenere una rappresentazione in complemento a due per un numero negativo, eseguire la rappresentazione binaria per valore assoluto del numero e invertire tutti i bit e aggiungere 1. Per esempio:

   4 Decimal = 0000 0000 0000 0100
1111 1111 1111 1011 Flip the Bits
-4 = 1111 1111 1111 1100 Add 1


Nota a -1 decimale = 1111 1111 1111 1111 in formato binario, che spiega perché considerata -1 valori logici true (tutti i bit = 1). Si tratta di una conseguenza di non avere operatori separati per i confronti logici e bit per bit. Spesso in Basic, è conveniente utilizzare nel codice riportato di seguito quando il programma effettueranno molti confronti logici. Questo semplifica notevolmente la leggibilità.

   CONST TRUE = -1
CONST FALSE = NOT TRUE


Si noti che l'aggiunta di qualsiasi combinazione di due integrano i numeri utilizzando i normali operazioni aritmetiche binarie produce il risultato corretto.

Complicazioni in virgola mobile

Ogni valore integer decimale può essere rappresentato esattamente da un valore integer binario; Tuttavia, ciò non avviene per i numeri frazionari. Infatti, ogni numero contraddittoria in base 10 saranno anche contraddittoria in qualsiasi sistema con una base inferiore a 10.


Per i dati binari, in particolare, numeri frazionari solo che possono essere rappresentati nel modulo p/q, dove q è una potenza di 2, possono essere espressa esattamente, con un numero finito di bit.


Le frazioni decimali anche comuni, come 0,0001, non può essere rappresentate esattamente in formato binario. (0,0001 è una frazione binaria ripetuta con un periodo di 104 bit)!


Ciò spiega perché un esempio semplice, ad esempio

   SUM = 0
FOR I% = 1 TO 10000
SUM = SUM + 0.0001
NEXT I%
PRINT SUM ' Theoretically = 1.0.


verrà 1.000054 stampa come output. Il piccolo errore di rappresentazione di 0,0001 nel sistema binario viene propagata alla somma.


Per lo stesso motivo, è sempre necessario prestare particolare attenzione quando confronti dei numeri reali. Nell'esempio riportato di seguito viene illustrato come un errore di programmazione comune.

   item1# = 69.82#
item2# = 69.20# + 0.62#
IF item1# = item2# then print "Equality!"


NON verrà stampato "Uguaglianza!" perché 69.82 non possono essere rappresentate esattamente nel formato binario, che fa sì che il valore risultante dall'assegnazione può essere leggermente diverso (in formato binario) rispetto al valore generato dall'espressione. In pratica, è consigliabile codificare sempre questi confronti in modo da consentire la tolleranza di alcuni. Per esempio:

   IF (item1# < 69.83#) AND (item1# > 69.81#) then print "Equal"


Verrà stampato "Uguale a".

IEEE formattare i numeri

QuickBasic per MS-DOS versione 3.0 è stato fornito con una versione MBF (Microsoft Binary Floating Point) e una versione IEEE (Institute of Electrical and Electronics Engineers) per i computer con un coprocessore matematico. QuickBasic per MS-DOS, 4.0 e versioni successive di soli IEEE. Microsoft ha scelto lo standard IEEE per rappresentare i valori a virgola mobile nelle versioni correnti di base per le ragioni principali:

  1. Per consentire di Basic per utilizzare i coprocessori matematici Intel, che utilizzano il formato IEEE. I coprocessori 80 x 87 serie Intel non funzionano con i numeri di formato binario di Microsoft.
  2. Per rendere interlanguage chiamata tra Basic, C, Pascal, FORTRAN e MASM molto più semplice. In caso contrario, routine di conversione avrebbero dovuto essere utilizzato per inviare i valori numerici da una lingua a altra.
  3. Per ottenere la consistenza. IEEE è accettata standard del settore per i compilatori C e FORTRAN.
Di seguito è un rapido confronto di IEEE e MBF rappresentazioni per un numero a precisione doppia:

               Sign Bits   Exponent Bits   Mantissa Bits
--------- ------------- -------------
IEEE 1 11 52 + 1 (Implied)
MBF 1 8 56


Per ulteriori informazioni sulle differenze tra IEEE e MBF rappresentazione a virgola mobile, la query delle parole seguenti nella Microsoft Knowledge Base:

   IEEE and floating and point and appnote


Notare che l'IEEE ha dedicato all'esponente, che consente di rappresentare una vasta gamma di valori di più bit. MBF ha più bit della mantissa, che consente di essere più precisi entro la gamma più ristretta.

Concetti generali di virgola mobile

È molto importante essere consapevoli che qualsiasi sistema binario in virgola mobile può rappresentare solo un numero finito di valori a virgola mobile nel formato esatto. Tutti gli altri valori devono essere ravvicinate in base al valore rappresentabile più vicino. Lo standard IEEE specifica il metodo di arrotondamento valori al valore rappresentabile "più vicino". QuickBasic per MS-DOS supporta lo standard e arrotonda secondo le regole di IEEE.


Inoltre, tenere presente che i numeri che possono essere rappresentati in IEEE sono distribuiti su una gamma molto ampia. È facile immaginare li su un numero di riga. Non vi sia elevata densità di numeri rappresentabili vicino 1.0 e -1.0 ma meno e meno come è verso l'infinito o 0.


L'obiettivo dello standard IEEE, appositamente studiata per i calcoli di progettazione, consiste nel massimizzare la precisione (per ottenere il più vicino possibile all'effettivo numero). La precisione indica il numero di cifre che è possibile rappresentare. Lo standard IEEE tenta di bilanciare il numero di bit dedicati all'esponente con il numero di bit utilizzati per la parte frazionaria del numero, per mantenere l'accuratezza e precisione entro limiti accettabili.

Dettagli IEEE

Numeri a virgola mobile sono rappresentati nel formato seguente, dove [Esponente] è l'esponente binario:

   X =  Fraction * 2^(exponent - bias)


[Frazione] è la parte frazionaria normalizzata del numero, normalizzata perché l'esponente è regolato in modo che il bit iniziale è sempre 1. In questo modo, esso non devono essere archiviati e si ottiene un bit in più di precisione. Questo è il motivo per cui non vi è un bit implicito. È possibile pensare ciò come notazione scientifica, in cui si manipola l'esponente per avere una cifra a sinistra del separatore decimale, tranne in formato binario, che è sempre possibile manipolare l'esponente in modo che il primo bit è 1, in quanto non esistono solo 1 e 0.


[bias] è il valore utilizzato per evitare di dover memorizzare esponenti negativi.


La differenza per numeri a precisione singola è 127 e 1023 (decimale) per numeri a precisione doppia.


I valori sono uguali a 0 tutti e tutti 1 (binario) sono riservati per la rappresentazione di casi particolari. Esistono anche altri casi particolari che indicano diverse condizioni di errore.

Esempi e precisione singola

2 = 1 * 2 ^ 1 = 0100 0000 0000 0000... 0000 0000 = 4000 0000 hex
Si noti il bit di segno è zero e l'esponente archiviato è 128 o 100 0000 0 in formato binario, che corrisponde a 127 più 1. La mantissa archiviata è (1) 000 0000... 0000 0000, che ha un'implicito iniziale 1 e una virgola binaria, pertanto la mantissa effettiva è 1.

-2 = -1 * 2 ^ 1 = 1100 0000 0000 0000... 0000 0000 = esadecimale 0000 C000
Simile a + 2 ad eccezione del fatto che viene impostato il bit di segno. Questo vale per tutti numeri a virgola mobile formato IEEE.

4 = 1 * 2 ^ 2 = 0100 0000 1000 0000... hex di 0000 0000 0000 = 4080
Stessa mantissa, l'esponente incrementa di uno (il valore distorto è 129 o 100 0000 1 in formato binario.

6 = 1,5 * 2 ^ 2 = 0100 0000 1100 0000... 0000 0000 = 0000 0 40C esadecimale
Stesso esponente, la mantissa è maggiore della metà, ovvero (1,) 100 0000... 0000 0000, che, poiché si tratta di una frazione binaria, è 1-1/2 (i valori delle cifre frazionarie sono 1/2, 1/4, 1/8, ecc.).

1 = 1 * 2 ^ 0 = 0011 1111 1000 0000... Hex di 0000 0000 0000 = 3F80
Stesso esponente delle altre potenze di 2, la mantissa è uno meno 2 127 o 011 1111 1 in formato binario.

.75 = 1,5 * 2 ^ -1 = 0011 1111 0100 0000... Hex di 0000 0000 0000 = 3F40
L'esponente distorto è 126, 011 1111 0 in formato binario e la mantissa è (1,) 100 0000... 0000 0000, 1-1/2.

1,25 = 2.5 * 2 ^ 1 = 0100 0000 0010 0000... 0000 0000 = 4020 0000 hex
Esattamente uguale a 2, eccetto il bit che rappresenta 1/4 è impostato nella mantissa.

0,1 = 1,6 * 2 ^ -4 = 0011 1101 1100 1100... 1100 1101 = 3DCC CCCD hex
1/10 è una frazione ripetuta in formato binario. La mantissa è appena inferiore a 1,6 e l'esponente distorto indica che 1,6 deve essere diviso per 16 (è 011 1101 1 in formato binario, ovvero 123 in formato decimale). L'esponente effettivo è 123-127 = - 4, che indica che il fattore per cui moltiplicare è 2 * * -4 = 1/16. Si noti che la mantissa archiviata è arrotondata per eccesso nell'ultimo bit. Si tratta di un tentativo di rappresentare il numero non rappresentabile più accurata possibile. (Il motivo di 1/10 e 1/100 sono non esattamente rappresentabile in formato binario è simile a quello che è non esattamente rappresentabile in formato decimale 1/3.)

0 = 1.0 * 2 ^ -128 = tutti zero - un caso speciale.

Altri comuni errori di virgola mobile

Di seguito sono comuni errori di virgola mobile:

  1. Gli errori di arrotondamento


    Questo errore verifica quando tutti i bit in un numero binario non può essere utilizzati nel calcolo.


    Esempio: Aggiunta di 0,0001 a 0.9900 (precisione singola)


    0,0001 verrà rappresentato come:
    (1) 10100011011011100010111 * 2^(-14+Bias) (13 iniziali 0s in formato binario)!
    0.9900 verrà rappresentato come:
    (1.)11111010111000010100011 * 2^(-1+Bias)
    A questo punto per aggiungere effettivamente questi numeri, i punti decimali (binari) devono essere allineati. Per questo devono essere Unnormalized. Di seguito viene aggiunta risultante:
           .000000000000011010001101 * 2^0  <- Only 11 of 23 Bits retained
    +.111111010111000010100011 * 2^0
    ________________________________
    .111111010111011100110000 * 2^0


    Si tratta di un errore di arrotondamento perché alcuni computer l'arrotondamento per spostare l'aggiunta. Altri semplicemente troncare. Errori di arrotondamento sono importanti da prendere in considerazione ogni volta che si desidera aggiungere o moltiplicare due valori molto diversi.
  2. Sottraendo i due valori uguali di quasi
           .1235
    -.1234
    _____
    .0001


    Questo verrà normalizzato. Si noti che sebbene i numeri di originali ogni disponeva di quattro cifre significative, il risultato sarà solo una cifra significativa.
  3. Overflow e underflow


    Ciò si verifica quando il risultato è troppo grande o troppo piccolo per essere rappresentato dal tipo di dati.
  4. Errore di quantizzazione


    Ciò si verifica con questi numeri non possono essere rappresentati nel formato esatto dallo standard della virgola mobile.
  5. Divisione per un numero molto piccolo


    Ciò può causare un errore di "divisione per zero" o può produrre risultati errati, come nell'esempio seguente:
          A = 112000000
    B = 100000
    C = 0.0009
    X = A - B / C


    In QuickBasic per MS-DOS, X ora è il valore 888887, anziché la risposta corretta, 900000.
  6. Errore di output


    Questo tipo di errore si verifica quando le funzioni di output modificano i valori che con cui lavorano.
Proprietà

ID articolo: 42980 - Ultima revisione: 30 gen 2017 - Revisione: 1

Feedback