2016-05-28 22 views
5

Assegno 0.4543543234343654632452452525254e-323 a double variabile a e lo stampo, sebbene sia inferiore a DBL_MIN, può ancora essere assegnato e stampato.perché è possibile stampare un numero doppio inferiore a DBL_MIN?

DBL_MAX: 1.79769e+308 
FLT_MAX: 3.40282e+38 
DBL_MIN: 2.22507e-308 
FLT_MIN: 1.17549e-38 
a: 4.94066e-324 

Perché questo accade?

+0

@flatmouse: 'DBL_MIN' non è il valore minimo, nel senso di segno, ma nel senso di grandezza, il valore più piccolo più grande (o minore) di zero. Quindi, in pratica, il numero che è il più vicino allo zero possibile. Il segno è irrilevante poiché è un bit specifico. – Jack

+0

tasto destro> seleziona e copia il testo di output. Non c'è bisogno di catturare lo screenshot che potrebbe marcire se il server muore –

+0

Un sacco di cose in virgola mobile in questo blog (non mio) https://randomascii.wordpress.com/2012/05/20/thats-not-normalthe-performance -of-odd-floats/e https://randomascii.wordpress.com/category/floating-point/ –

risposta

12

In realtà DBL_MIN non è il valore più piccolo ma il più piccolo normalized value che sia rappresentabile.

La differenza è la cifra iniziale con 1 per i valori normalizzati, mentre è 0 per i numeri denormali. Tenete presente che denormal numbers potrebbe soffrire di gravi problemi di prestazioni su hardware con unità di elaborazione mobile che non è in grado di gestirli nell'hardware.

Ma il vostro valore, 0.454354e-323, che corrisponde a 4.545354e-324 è più piccolo del più piccolo numero denormal representble con un double, anzi si arriva arrotondato a 4.94066e-324 che è il vero più piccolo numero che può essere memorizzata in un double.

+0

@flatmouse: 'DBL_MIN' non è il numero più piccolo che può essere rappresentato in un valore' double' quindi non c'è niente di strano nell'output del programma dell'OP. – Jack

+1

@flatmouse forse hai letto male la domanda - mi sembra che questa risposta risponda alla domanda e la tua non ha nulla a che fare con essa –

-1

Il comportamento IEEE 754-1985 è più facile da capire guardando direttamente i bit.

Il numero following program mostra il segno, la mantissa e l'esponente per ciascun numero e il modello di bit per ciascuno.

#include <iostream> 
#include <limits> 
#include <iomanip> 
#include <bitset> 
#include <unordered_map> 
#include <string> 
#include <tuple> 
#include <sstream> 
#include <cmath> 

using Values = std::tuple<double,std::string>; 
using MyMap = std::unordered_map<std::string,Values>; 

std::string convert_to_string(double val) 
{ 
    auto ptr{reinterpret_cast<const unsigned long long*>(&val)}; 
    auto ival{*ptr}; 
    unsigned long long mask{1ULL << 63}; 
    std::string bitstring; 
    for (size_t i{0}; i<64; ++i) { 
     auto bitval{(ival&mask)>0}; 
     mask >>= 1; 
     bitval? bitstring.push_back('1') : bitstring.push_back('0'); 
    } 

    return bitstring; 
} 

std::ostream& operator<<(std::ostream& os,std::pair<std::string,Values> mypair) 
{ 
    auto name{mypair.first}; 
    auto values{mypair.second}; 
    auto dvalue{std::get<0>(values)}; 
    auto bitsetvalue{std::get<1>(values)}; 
    char sign_symbol{bitsetvalue.substr(0,1)=="0"?'+':'-'}; 
    std::bitset<1> sign{bitsetvalue.substr(0,1)}; 
    std::bitset<11> biased_exponent{bitsetvalue.substr(1,11)}; 
    std::bitset<52> mantissa{bitsetvalue.substr(12,52)}; 
    auto mantissa_value{mantissa.to_ullong()}; 
    double mantissa_value_double{static_cast<double>(mantissa_value)}; 
    auto biased_exponent_value{static_cast<signed long long>(biased_exponent.to_ulong())}; 
    bool denormal{biased_exponent_value==0}; 
    std::string denormal_text{denormal?"denormal":""}; 
    signed long long exponent_value{denormal?-1022:biased_exponent_value-1023}; 
    std::string mantissa_with_leading_digit{std::string((denormal?"0.":"1.")) + mantissa.to_string()}; 
    double mantissa_with_leading_digit_value{double{denormal?0.0F:1.0F}+(mantissa_value_double * std::pow(2.0F,-52.0F))}; 
    std::bitset<11> unbiased_exponent{static_cast<unsigned long long>(std::abs(exponent_value))}; 
    char exponent_sign_symbol{exponent_value<0?'-':' '}; 

    std::cout << std::setw(60) << name << std::setw(20) << dvalue << '\n'; 
    std::cout << std::setw(60) << "Binary (biased exponent, hidden leading binary digit)" << std::setw(30) << sign << std::setw(15) << biased_exponent << std::setw(10) << denormal_text << std::setw(60) << mantissa << '\n'; 
    std::cout << std::setw(60) << "Binary (unbiased exponent, visible leading binary digit)" << std::setw(30) << sign << std::setw(4) << exponent_sign_symbol << unbiased_exponent << std::setw(10) << denormal_text << std::setw(60) << mantissa_with_leading_digit << '\n'; 
    std::cout << std::setw(60) << "Decimal (biased exponent)        " << std::setw(30) << sign_symbol << std::setw(15) << biased_exponent_value << std::setw(10) << denormal_text << std::setw(60) << mantissa_with_leading_digit_value << '\n'; 
    std::cout << std::setw(60) << "Decimal (unbiased exponent)        " << std::setw(30) << sign_symbol << std::setw(15) << exponent_value << std::setw(10) << denormal_text << std::setw(60) << mantissa_with_leading_digit_value << '\n'; 
    std::cout << std::setw(50) << mantissa_with_leading_digit_value << " * 2**" << std::setw(5) << exponent_value << " = " << std::setw(12) << mantissa_with_leading_digit_value*std::pow(2.0F,exponent_value) << '\n'; 
    std::cout << std::setw(180) << std::setfill('-') << '\n' << std::setfill(' ') << "\n\n\n"; 

    return os; 
} 

int main() 
{ 
    double max_double = std::numeric_limits<double>::max(); 
    double lowest_double = std::numeric_limits<double>::min(); 
    double stored_value{0.4543543234343654632452452525254e-323}; 


    MyMap values{ 
     {"Lowest",std::make_tuple(lowest_double, convert_to_string(lowest_double))}, 
     {"Highest",std::make_tuple(max_double, convert_to_string(max_double))}, 
     {"0.4543543234343654632452452525254e-323",std::make_tuple(stored_value, convert_to_string(stored_value))} 

    }; 

    std::cout << std::setw(60) << "Variable name" << std::setw(20) << "Decimal value" << std::setw(10) << "Sign" << std::setw(15) << "Exponent" << std::setw(10) << "Exp. Rule" << std::setw(60) << "Mantissa" << std::setw(30) << '\n'; 
    std::cout << std::setw(180) << std::setfill('-') << '\n' << std::setfill(' '); 
    for (auto& i : values) 
     std::cout << i; 

    return 0; 
} 

uscita:

           Variable name  Decimal value  Sign  Exponent Exp. Rule             Mantissa 
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
                 Lowest  2.22507e-308 
    Binary (biased exponent, hidden leading binary digit)        0 00000000001     0000000000000000000000000000000000000000000000000000 
    Binary (unbiased exponent, visible leading binary digit)        0 -01111111110    1.0000000000000000000000000000000000000000000000000000 
    Decimal (biased exponent)               +    1                  1 
    Decimal (unbiased exponent)               +   -1022                  1 
               1 * 2**-1022 = 2.22507e-308 
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 



                Highest  1.79769e+308 
    Binary (biased exponent, hidden leading binary digit)        0 11111111110     1111111111111111111111111111111111111111111111111111 
    Binary (unbiased exponent, visible leading binary digit)        0 01111111111    1.1111111111111111111111111111111111111111111111111111 
    Decimal (biased exponent)               +   2046                  2 
    Decimal (unbiased exponent)               +   1023                  2 
               2 * 2** 1023 = 1.79769e+308 
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 



         0.4543543234343654632452452525254e-323  4.94066e-324 
    Binary (biased exponent, hidden leading binary digit)        0 00000000000 denormal  0000000000000000000000000000000000000000000000000001 
    Binary (unbiased exponent, visible leading binary digit)        0 -01111111110 denormal  0.0000000000000000000000000000000000000000000000000001 
    Decimal (biased exponent)               +    0 denormal             2.22045e-16 
    Decimal (unbiased exponent)               +   -1022 denormal             2.22045e-16 
             2.22045e-16 * 2**-1022 = 4.94066e-324 
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
Problemi correlati