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
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@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
tasto destro> seleziona e copia il testo di output. Non c'è bisogno di catturare lo screenshot che potrebbe marcire se il server muore –
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/ –