2013-03-26 10 views
5

Qual è l'intervallo esatto di numeri interi (contigui) che possono essere espressi come double (o float?) La ragione per cui lo chiedo è perché sono curioso di questions such as this one quando si verificherà una perdita di precisione.Intervallo di numeri interi che possono essere espressi esattamente come float/doubles

Cioè

  1. Qual è il minimo intero positivo m tale che m+1 non può essere espresso esattamente come un doppio (risp. Float)?
  2. Qual è il più grande numero intero negativo -n tale che -n-1 non possa essere espresso con precisione come doppio (risp. Float)? (Potrebbe essere lo stesso di sopra).

Ciò significa che ogni numero intero compreso tra -n e m ha una rappresentazione a virgola mobile esatta. Sto fondamentalmente cercando la gamma [-n, m] sia per i galleggianti che per i doppi.

Limitiamo l'ambito alle rappresentazioni a virgola mobile a 32 e 64 bit standard IEEE 754. So che il float ha 24 bit di precisione e il doppio ha 53 bit (entrambi con un piccolo bit nascosto), ma a causa della complessità della rappresentazione in virgola mobile sto cercando una risposta autorevole per questo. Per favore non agitare le mani!

(risposta ideale sarebbe dimostrare che tutti gli interi da 0 a m sono esprimibili, e che m+1 non lo è.)

risposta

6

Dal momento che si sta chiedendo sui tipi IEEE in virgola mobile, la lingua non ha importanza.

#include <iostream> 
using namespace std; 

int main(){ 

    float f0 = 16777215.; // 2^24 - 1 
    float f1 = 16777216.; // 2^24 
    float f2 = 16777217.; // 2^24 + 1 

    cout << (f0 == f1) << endl; 
    cout << (f1 == f2) << endl; 

    double d0 = 9007199254740991.; // 2^53 - 1 
    double d1 = 9007199254740992.; // 2^53 
    double d2 = 9007199254740993.; // 2^53 + 1 

    cout << (d0 == d1) << endl; 
    cout << (d1 == d2) << endl; 
} 

uscita:

0 
1 
0 
1 

Quindi il limite per galleggiante è 2^24. E il limite per il doppio è 2^53. I negativi sono gli stessi poiché l'unica differenza è il bit del segno.

+0

Ho taggato con le lingue poiché non c'era traffico per gli altri tag che ho provato. Grazie per la tua risposta! –

+0

Kyurem è morto nella sua analisi. Ma se vuoi una soluzione empirica, prova semplicemente con un ciclo for: 'float f = 0; for (;; ++ f) {if (f == (f + 1)) {cout << f; rompere; }} '. Simile per doppi e negativi. –

Problemi correlati