numeric_limits<float> questions

J

john

The code:

#include <iostream>
#include <limits>


int main()
{
using namespace std;

typedef numeric_limits<float> limitsf;

cout<< boolalpha<< " radix= "<< limitsf::radix<< endl
<<" digits= "<< limitsf::digits<< endl
<< " digits10= "<< limitsf::digits10<< endl
<< " min()= "<< limitsf::min()<< endl
<< " max()= "<< limitsf::max()<< endl
<< " epsilon()= "<< limitsf::epsilon()<< endl
<< " min_exponent= "<< limitsf::min_exponent<< endl
<< " min_exponent10= "<< limitsf::min_exponent10<< endl
<< " max_exponent= "<< limitsf::max_exponent<< endl
<< " max_exponent10= "<< limitsf::max_exponent10<< endl
<< " is_iec559= "<< limitsf::is_iec559<< endl
<< " traps= "<< limitsf::traps<< endl;

}


in my system produces:


[john@localhost src]$ ./foobar-cpp
radix= 2
digits= 24
digits10= 6
min()= 1.17549e-38
max()= 3.40282e+38
epsilon()= 1.19209e-07
min_exponent= -125
min_exponent10= -37
max_exponent= 128
max_exponent10= 38
is_iec559= true
traps= false

[john@localhost src]$



numeric_limits<float> questions:

Q1: min() shows up as a positive number. Why?

Q2: min() contains e-38, while min_exponent10== -37.
 
D

Duane Hebert

numeric_limits said:
Q1: min() shows up as a positive number. Why?

Because min(), for floating point types, shows the
smallest positive value and not the minimum value
like integral types. Not sure why this is the case.
I would have preferred min() to work the same in all cases.
Maybe add a smallest() function to do what min() does now.

At any rate, what you probably want in -max().
 
C

Chip Coldwell

john said:
The code:

#include <iostream>
#include <limits>


int main()
{
using namespace std;

typedef numeric_limits<float> limitsf;

cout<< boolalpha<< " radix= "<< limitsf::radix<< endl
<<" digits= "<< limitsf::digits<< endl
<< " digits10= "<< limitsf::digits10<< endl
<< " min()= "<< limitsf::min()<< endl
<< " max()= "<< limitsf::max()<< endl
<< " epsilon()= "<< limitsf::epsilon()<< endl
<< " min_exponent= "<< limitsf::min_exponent<< endl
<< " min_exponent10= "<< limitsf::min_exponent10<< endl
<< " max_exponent= "<< limitsf::max_exponent<< endl
<< " max_exponent10= "<< limitsf::max_exponent10<< endl
<< " is_iec559= "<< limitsf::is_iec559<< endl
<< " traps= "<< limitsf::traps<< endl;

}


in my system produces:


[john@localhost src]$ ./foobar-cpp
radix= 2
digits= 24
digits10= 6
min()= 1.17549e-38
max()= 3.40282e+38
epsilon()= 1.19209e-07
min_exponent= -125
min_exponent10= -37
max_exponent= 128
max_exponent10= 38
is_iec559= true
traps= false

That looks wrong to me. I think min_exponent should be -126. On my
system, this program

#include <iostream>
#include <limits>

template <typename float_t, typename sint_t, typename uint_t, int mbits, int ebits>
class ieee_float {
#ifdef __BIG_ENDIAN__
uint_t s:1;
uint_t e:ebits;
uint_t m:mbits;
#else
uint_t m:mbits;
uint_t e:ebits;
uint_t s:1;
#endif

public:
static const uint_t mdenom = ((uint_t)1 << mbits);
static const uint_t ebias = ((uint_t)1 << (ebits - 1)) - 1;
sint_t sign(void) const { return 1 - 2*s; }
sint_t exponent(void) const { return e ? e - ebias : -(ebias - 1); }
uint_t mantissa(void) const { return ((uint_t)(!!e) << mbits) | m; }
bool infinity(void) const { return (e == ((1 << ebits) - 1)) && (m == 0); }
bool nan(void) const { return (e == ((1 << ebits) - 1)) && (m != 0); }
bool denormal(void) const { return (e == 0) && (m != 0); }
ieee_float(float_t f) { *(float_t *)this = f; }
ieee_float(uint_t u) { *(uint_t *)this = u; }
operator float_t() const { return *(float_t *)this; }
operator uint_t() const { return *(uint_t *)this; }
};

typedef ieee_float<float, int, unsigned, 23, 8> single_precision;
typedef ieee_float<double, long long, unsigned long long, 52, 11> double_precision;

int main(int argc, char *argv[])
{
single_precision d(std::numeric_limits<float>::min());
std::cout << "decimal: " << (float) d << std::endl;
std::cout << "hexadecimal: " << std::hex << (unsigned) d << std::dec << std::endl;
std::cout << "sign: " << d.sign() << std::endl;
std::cout << "exponent: " << d.exponent() << std::endl;
std::cout << "mantissa: " << d.mantissa() << "/" << d.mdenom << std::endl;
std::cout << "min exponent: " << std::numeric_limits<float>::min_exponent << std::endl;
return 0;
}

produced this output:

$ ./test
decimal: 1.17549e-38
hexadecimal: 800000
sign: 1
exponent: -126
mantissa: 8388608/8388608
min exponent: -125

Strange that the exponent on "std::numeric_limits<float>::min()" would
be less than "std::numeric_limits<float>::min_exponent".

Chip
 
J

john

Chip said:
That looks wrong to me. I think min_exponent should be -126. On my
system, this program

#include <iostream>
#include <limits>

template <typename float_t, typename sint_t, typename uint_t, int mbits, int ebits>
class ieee_float {
#ifdef __BIG_ENDIAN__
uint_t s:1;
uint_t e:ebits;
uint_t m:mbits;
#else
uint_t m:mbits;
uint_t e:ebits;
uint_t s:1;
#endif

public:
static const uint_t mdenom = ((uint_t)1 << mbits);
static const uint_t ebias = ((uint_t)1 << (ebits - 1)) - 1;
sint_t sign(void) const { return 1 - 2*s; }
sint_t exponent(void) const { return e ? e - ebias : -(ebias - 1); }
uint_t mantissa(void) const { return ((uint_t)(!!e) << mbits) | m; }
bool infinity(void) const { return (e == ((1 << ebits) - 1)) && (m == 0); }
bool nan(void) const { return (e == ((1 << ebits) - 1)) && (m != 0); }
bool denormal(void) const { return (e == 0) && (m != 0); }
ieee_float(float_t f) { *(float_t *)this = f; }
ieee_float(uint_t u) { *(uint_t *)this = u; }
operator float_t() const { return *(float_t *)this; }
operator uint_t() const { return *(uint_t *)this; }
};

typedef ieee_float<float, int, unsigned, 23, 8> single_precision;
typedef ieee_float<double, long long, unsigned long long, 52, 11> double_precision;

int main(int argc, char *argv[])
{
single_precision d(std::numeric_limits<float>::min());
std::cout << "decimal: " << (float) d << std::endl;
std::cout << "hexadecimal: " << std::hex << (unsigned) d << std::dec << std::endl;
std::cout << "sign: " << d.sign() << std::endl;
std::cout << "exponent: " << d.exponent() << std::endl;
std::cout << "mantissa: " << d.mantissa() << "/" << d.mdenom << std::endl;
std::cout << "min exponent: " << std::numeric_limits<float>::min_exponent << std::endl;
return 0;
}

produced this output:

$ ./test
decimal: 1.17549e-38
hexadecimal: 800000
sign: 1
exponent: -126
mantissa: 8388608/8388608
min exponent: -125

Strange that the exponent on "std::numeric_limits<float>::min()" would
be less than "std::numeric_limits<float>::min_exponent".

Chip


Your code produces in my system:


[john@localhost src]$ ./foobar-cpp
decimal: 1.17549e-38
hexadecimal: 800000
sign: 1
exponent: -126
mantissa: 8388608/8388608
min exponent: -125

[john@localhost src]$

It looks like we get the same values. My OS is CentOS 5.0, with
"gcc version 4.1.1 20070105 (Red Hat 4.1.1-52)".
 
C

Chip Coldwell

john said:
Chip said:
That looks wrong to me. I think min_exponent should be -126. On my
system, this program

#include <iostream>
#include <limits>

template <typename float_t, typename sint_t, typename uint_t, int mbits, int ebits>
class ieee_float {
#ifdef __BIG_ENDIAN__
uint_t s:1;
uint_t e:ebits;
uint_t m:mbits;
#else
uint_t m:mbits;
uint_t e:ebits;
uint_t s:1;
#endif

public:
static const uint_t mdenom = ((uint_t)1 << mbits);
static const uint_t ebias = ((uint_t)1 << (ebits - 1)) - 1;
sint_t sign(void) const { return 1 - 2*s; }
sint_t exponent(void) const { return e ? e - ebias : -(ebias - 1); }
uint_t mantissa(void) const { return ((uint_t)(!!e) << mbits) | m; }
bool infinity(void) const { return (e == ((1 << ebits) - 1)) && (m == 0); }
bool nan(void) const { return (e == ((1 << ebits) - 1)) && (m != 0); }
bool denormal(void) const { return (e == 0) && (m != 0); }
ieee_float(float_t f) { *(float_t *)this = f; }
ieee_float(uint_t u) { *(uint_t *)this = u; }
operator float_t() const { return *(float_t *)this; }
operator uint_t() const { return *(uint_t *)this; }
};

typedef ieee_float<float, int, unsigned, 23, 8> single_precision;
typedef ieee_float<double, long long, unsigned long long, 52, 11> double_precision;

int main(int argc, char *argv[])
{
single_precision d(std::numeric_limits<float>::min());
std::cout << "decimal: " << (float) d << std::endl;
std::cout << "hexadecimal: " << std::hex << (unsigned) d << std::dec << std::endl;
std::cout << "sign: " << d.sign() << std::endl;
std::cout << "exponent: " << d.exponent() << std::endl;
std::cout << "mantissa: " << d.mantissa() << "/" << d.mdenom << std::endl;
std::cout << "min exponent: " << std::numeric_limits<float>::min_exponent << std::endl;
return 0;
}

produced this output:

$ ./test
decimal: 1.17549e-38
hexadecimal: 800000
sign: 1
exponent: -126
mantissa: 8388608/8388608
min exponent: -125

Strange that the exponent on "std::numeric_limits<float>::min()" would
be less than "std::numeric_limits<float>::min_exponent".

Chip


Your code produces in my system:


[john@localhost src]$ ./foobar-cpp
decimal: 1.17549e-38
hexadecimal: 800000
sign: 1
exponent: -126
mantissa: 8388608/8388608
min exponent: -125

[john@localhost src]$

It looks like we get the same values. My OS is CentOS 5.0, with
"gcc version 4.1.1 20070105 (Red Hat 4.1.1-52)".

Well, I asked the oracle, and he quoted me chapter and verse:

Similarly ISO C++98, [lib.numeric.limits.members]/{23,24,26,27}:
static const int min_exponent;
Minimum negative integer such that radix raised to the power of one less
than that integer is a normalized floating point number.189)
Meaningful for all floating point types.
static const int max_exponent;
Maximum positive integer such that radix raised to the power one less
than that integer is a representable finite floating point number.191)
Meaningful for all floating point types.

189) Equivalent to FLT_MIN_EXP, DBL_MIN_EXP, LDBL_MIN_EXP.
191) Equivalent to FLT_MAX_EXP, DBL_MAX_EXP, LDBL_MAX_EXP.

So "min_exponent" is the minimum exponent plus one (of course!).

What I haven't been able to discover is what motivated this intuition
defying choice.

Chip
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top