P
Prune Tracy
Hello. As practice in programming using templates, and for interest's
sake, I wrote some code to see how floating point numbers are stored
on my system. I hoped to be able to use it like:
std::cout << internal_rep(1.0F) << std::endl;
std::cout << internal_rep(1.0) << std::endl;
and it would give me a hexadecimal output of the bytes making up the
storage of 1.0 in float and double format.
The code I have written to do this is as follows:
#include <iostream>
#include <iomanip>
#include <vector>
#include <memory>
template<typename T>
class internal_rep_class;
template<typename T>
std:stream& operator<<(std:stream& os,
const std::auto_ptr<internal_rep_class<T> >& rep) {
for (unsigned i = 0; i < rep->bytes.size(); ++i)
os << std::hex
<< static_cast<unsigned int>(rep->bytes) << ' ';
return os;
}
template<typename T>
class internal_rep_class {
public:
friend std:stream& operator<< <>(std:stream&,
const std::auto_ptr<internal_rep_class<T> >& rep);
internal_rep_class(T t) {
for (unsigned i = 0; i < sizeof(T); ++i)
bytes.push_back(
*(reinterpret_cast<unsigned char*>(&t)+i));
}
private:
std::vector<unsigned char> bytes;
};
template<typename T>
std::auto_ptr<internal_rep_class<T> > internal_rep(T t) {
return std::auto_ptr<internal_rep_class<T> >(
new internal_rep_class<T>(t));
}
int main() {
std::cout << internal_rep(1.0) << std::endl;
return 0;
}
The code apparently does what I want, but it seems overly complicated
to me. In particular the use of std::auto_ptr seems like overkill.
The reason for writing the internal_rep function was to allow me to
write
std::cout << internal_rep(1.0) << std::endl;
rather than the slightly more inconvenient
std::cout << internal_rep_class<double>(1.0) << std::endl;
Initially I wanted internal_rep to return a const reference. However
my understanding is that this would not work: for even though it is
legal to bind a const reference to a temporary, this reference would
be destroyed at the completion of internal_rep, and a copy of it would
actually be returned. Is this correct? (My compiler issued a warning
over the code.)
So I wonder, is there a better way that avoids the use of
std::auto_ptr or similar?
On a slightly related note, I notice that on my system
std::numeric_limits<double>::has_quiet_NaN
and
std::numeric_limits<double>::has_signaling_NaN
are both false, and
std::numeric_limits<double>::quiet_NaN()
and
std::numeric_limits<double>::signaling_NaN()
return 0.0. However
std::cout << (0.0 / 0.0);
outputs NaN. This seems a bit counterintuitive - is it unusual?
sake, I wrote some code to see how floating point numbers are stored
on my system. I hoped to be able to use it like:
std::cout << internal_rep(1.0F) << std::endl;
std::cout << internal_rep(1.0) << std::endl;
and it would give me a hexadecimal output of the bytes making up the
storage of 1.0 in float and double format.
The code I have written to do this is as follows:
#include <iostream>
#include <iomanip>
#include <vector>
#include <memory>
template<typename T>
class internal_rep_class;
template<typename T>
std:stream& operator<<(std:stream& os,
const std::auto_ptr<internal_rep_class<T> >& rep) {
for (unsigned i = 0; i < rep->bytes.size(); ++i)
os << std::hex
<< static_cast<unsigned int>(rep->bytes) << ' ';
return os;
}
template<typename T>
class internal_rep_class {
public:
friend std:stream& operator<< <>(std:stream&,
const std::auto_ptr<internal_rep_class<T> >& rep);
internal_rep_class(T t) {
for (unsigned i = 0; i < sizeof(T); ++i)
bytes.push_back(
*(reinterpret_cast<unsigned char*>(&t)+i));
}
private:
std::vector<unsigned char> bytes;
};
template<typename T>
std::auto_ptr<internal_rep_class<T> > internal_rep(T t) {
return std::auto_ptr<internal_rep_class<T> >(
new internal_rep_class<T>(t));
}
int main() {
std::cout << internal_rep(1.0) << std::endl;
return 0;
}
The code apparently does what I want, but it seems overly complicated
to me. In particular the use of std::auto_ptr seems like overkill.
The reason for writing the internal_rep function was to allow me to
write
std::cout << internal_rep(1.0) << std::endl;
rather than the slightly more inconvenient
std::cout << internal_rep_class<double>(1.0) << std::endl;
Initially I wanted internal_rep to return a const reference. However
my understanding is that this would not work: for even though it is
legal to bind a const reference to a temporary, this reference would
be destroyed at the completion of internal_rep, and a copy of it would
actually be returned. Is this correct? (My compiler issued a warning
over the code.)
So I wonder, is there a better way that avoids the use of
std::auto_ptr or similar?
On a slightly related note, I notice that on my system
std::numeric_limits<double>::has_quiet_NaN
and
std::numeric_limits<double>::has_signaling_NaN
are both false, and
std::numeric_limits<double>::quiet_NaN()
and
std::numeric_limits<double>::signaling_NaN()
return 0.0. However
std::cout << (0.0 / 0.0);
outputs NaN. This seems a bit counterintuitive - is it unusual?