Connecting Tech Pros Worldwide Help | Site Map

numeric_limits<float> questions

john
Guest
 
Posts: n/a
#1: Oct 31 '07
The code:

#include <iostream>
#include <limits>


int main()
{
using namespace std;

typedef numeric_limits<floatlimitsf;

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<floatquestions:

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

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


Duane Hebert
Guest
 
Posts: n/a
#2: Oct 31 '07

re: numeric_limits<float> questions


numeric_limits<floatquestions:
Quote:
>
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().




Chip Coldwell
Guest
 
Posts: n/a
#3: Nov 1 '07

re: numeric_limits<float> questions


john <john@no.spamwrites:
Quote:
The code:
>
#include <iostream>
#include <limits>
>
>
int main()
{
using namespace std;
>
typedef numeric_limits<floatlimitsf;
>
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, 8single_precision;
typedef ieee_float<double, long long, unsigned long long, 52, 11double_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

--
Charles M. "Chip" Coldwell
"Turn on, log in, tune out"
Somerville, Massachusetts, New England
john
Guest
 
Posts: n/a
#4: Nov 1 '07

re: numeric_limits<float> questions


Chip Coldwell wrote:
Quote:
>
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, 8single_precision;
typedef ieee_float<double, long long, unsigned long long, 52, 11double_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)".

Chip Coldwell
Guest
 
Posts: n/a
#5: Nov 1 '07

re: numeric_limits<float> questions


john <john@no.spamwrites:
Quote:
Chip Coldwell wrote:
Quote:
>>
>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, 8single_precision;
>typedef ieee_float<double, long long, unsigned long long, 52, 11double_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

--
Charles M. "Chip" Coldwell
"Turn on, log in, tune out"
Somerville, Massachusetts, New England
Closed Thread