standard encoding for float?

J

julvr

Is the encoding for float platform independent? That is, if I take
the four bytes, stick them into an ethernet packet send them to
another machine, then (after endian swapping and alignment), set a
float pointer to point at those four bytes, will I get the same
value? It seems to work on the plaforms I have, but this is suppose
to work for any machine types -- so I guess my question is, is the
encoding of float standardized?

Thanks

John
 
P

peter koch

Is the encoding for float platform independent?  That is, if I take
the four bytes, stick them into an ethernet packet send them to
another machine, then (after endian swapping and alignment), set a
float pointer to point at those four bytes, will I get the same
value?  It seems to work on the plaforms I have, but this is suppose
to work for any machine types -- so I guess my question is, is the
encoding of float standardized?

Yes. And a float might not be four bytes. Depending on how portable
you want your code to become you might stick to e.g. IEEE floats. If
not you should also consider e.g. what should happen in case you send
a float to a machine that can't represent the value.

/Peter
 
E

Erik Wikström

Is the encoding for float platform independent? That is, if I take
the four bytes, stick them into an ethernet packet send them to
another machine, then (after endian swapping and alignment), set a
float pointer to point at those four bytes, will I get the same
value? It seems to work on the plaforms I have, but this is suppose
to work for any machine types -- so I guess my question is, is the
encoding of float standardized?

No, while IEEE 754 is the most common format there is no guarantee it is
used, and even if it is there is still the endianness issue. If you want
to send floats/doubles across the network then select a suitable
serialisation format and use it (unless you can guarantee that all
communicating hosts uses the same format). A simple solution is to use a
stringstream to convert the number to text and then back again.
 
J

julvr

No, while IEEE 754 is the most common format there is no guarantee it is
used, and even if it is there is still the endianness issue. If you want
to send floats/doubles across the network then select a suitable
serialisation format and use it (unless you can guarantee that all
communicating hosts uses the same format). A simple solution is to use a
stringstream to convert the number to text and then back again.

Thanks for the replies -- I was suspecting that this would be the
case, but I just wanted to double check.
 
J

jason.cipriani

No, while IEEE 754 is the most common format there is no guarantee it is
used, and even if it is there is still the endianness issue. If you want
to send floats/doubles across the network then select a suitable
serialisation format and use it (unless you can guarantee that all
communicating hosts uses the same format). A simple solution is to use a
stringstream to convert the number to text and then back again.

What is a good way to do this (send a floating-point value from one
machine to another) without losing precision (and ideally without
increasing bandwidth)? I've run into this issue frequently.

At the bare minimum, do you know of a way to -check- what format a
"float" is in so that I could at least make the application say "not
implemented for this machine, please contact the author" instead of
silently screwing up?

I have done things like:

assert(sizeof(float) == 4);

At compile time, to state my assumption, but that doesn't account for
different 4-byte formats. I suppose I could probably cover many, but
not all, cases by sending a value over the network and verifying that
it is the expected value when packed back into a "float" on the other
end.

Jason
 
J

James Kanze

Is the encoding for float platform independent? That is, if I
take the four bytes, stick them into an ethernet packet send
them to another machine, then (after endian swapping and
alignment), set a float pointer to point at those four bytes,
will I get the same value? It seems to work on the plaforms I
have, but this is suppose to work for any machine types -- so
I guess my question is, is the encoding of float standardized?

Yes and no. There is a "standard" encoding, but it's
independant of the C++ standard, and not used everywhere.

Off hand, I know of at least four different encodings in use on
machines being sold today. Most, however, are used on
mainframes, for historical reasons: if you're only goal is to
communicate between mainstream Unix machines and Windows, then
you can probably count on IEEE format: type pun your float to a
uin32_t, and transmit that. (Note that even integers have
different formats on some machines: 36 bit 1's complement, or 48
bit signed magnitude, at least, are still in use today. Again,
however, not everyone necessarily has to worry about these.)
 
J

James Kanze

What is a good way to do this (send a floating-point value
from one machine to another) without losing precision (and
ideally without increasing bandwidth)? I've run into this
issue frequently.

There is no absolute answer. To begin with, if the source
machine has greater precision than the target machine, it is
impossible, since the target machine won't be able to represent
the value with greater precision than it has. If the reverse is
true, it's also an interesting question: if I send the results
of 1.0/3.0, what the target machine receives won't be the
results of 1.0/3.0.

In general, the protocol will specify a format, with whatever
precision it supports. If the source machine has greater
precision, it will round, and if the target machine has greater
precision, some possible values will never be sent. The one
exception I know is BER encoding, in which the source machine
sends the value in its native encoding, with information about
the encoding. This means that there is never a loss of
precision when communicating between machines with the same
representation, but it also means a lot of extra complexity. An
awful lot. (In addition to sending the sign, the exponant and
the mantissa as separate fields, it also has to send informat as
to how to interpret those fields.)
At the bare minimum, do you know of a way to -check- what
format a "float" is in so that I could at least make the
application say "not implemented for this machine, please
contact the author" instead of silently screwing up?

There are a number of useful values in either <cfloat> or
<limits>. Those in <cfloat> are macros which evaluate to
constant expressions, which when integral can be used in the
preprocessor, e.g. for conditional compilation. (The ones that
would interest you here are xxx_RADIX, xxx_MANT_DIG, xxx_MIN_EXP
and xxx_MAX_EXP, where xxx is one of FLT, DBL OR LDBL.)
 
E

Erik Wikström

There is no absolute answer. To begin with, if the source
machine has greater precision than the target machine, it is
impossible, since the target machine won't be able to represent
the value with greater precision than it has. If the reverse is
true, it's also an interesting question: if I send the results
of 1.0/3.0, what the target machine receives won't be the
results of 1.0/3.0.

In general, the protocol will specify a format, with whatever
precision it supports. If the source machine has greater
precision, it will round, and if the target machine has greater
precision, some possible values will never be sent. The one
exception I know is BER encoding, in which the source machine
sends the value in its native encoding, with information about
the encoding. This means that there is never a loss of
precision when communicating between machines with the same
representation, but it also means a lot of extra complexity. An
awful lot. (In addition to sending the sign, the exponant and
the mantissa as separate fields, it also has to send informat as
to how to interpret those fields.)


There are a number of useful values in either <cfloat> or
<limits>. Those in <cfloat> are macros which evaluate to
constant expressions, which when integral can be used in the
preprocessor, e.g. for conditional compilation. (The ones that
would interest you here are xxx_RADIX, xxx_MANT_DIG, xxx_MIN_EXP
and xxx_MAX_EXP, where xxx is one of FLT, DBL OR LDBL.)

Or one can mandate IEEE 754 (also known as IEC 559) by using the
is_iec559() function of the numeric_limits class. Combine this with
sizeof() and all you have to worry about is endianess issues (which you
might be able to solve using ntohl() in POSIX).
 
J

julvr

Or one can mandate IEEE 754 (also known as IEC 559) by using the
is_iec559() function of the numeric_limits class. Combine this with
sizeof() and all you have to worry about is endianess issues (which you
might be able to solve using ntohl() in POSIX).

While this allows you to tell whether you are using IEEE 754, it
cannot force the machine to use it.

What I ended up doing was using frexp to get the mantassa and the
exponent, and wrotes those to bytes (assuming a 24 mantassa and 8 bit
exponent). If my exponent exceeded 8 bits, I failed, and if my
mantassa exceeded 24 bits, I would truncate. It seems to work quite
well, but I haven't tried it on to many platforms yet.
 
J

jason.cipriani

Thanks for the great response, James. The stuff in <cfloat> is
especially useful.

- Jason
 
J

James Kanze

On 2008-03-19 11:49, James Kanze wrote:

[...]
Or one can mandate IEEE 754 (also known as IEC 559) by using
the is_iec559() function of the numeric_limits class. Combine
this with sizeof() and all you have to worry about is
endianess issues (which you might be able to solve using
ntohl() in POSIX).

But that's runtime, and not compile time.

In C99 (and in C++0x?), you can test whether __STDC_IEC_559__ is
defined. In practice, however, of the five compilers I have
ready access too (VC++ and g++ under Windows, g++ under Linux,
and g++ and Sun CC under Solaris), only g++ under Linux tests
true, although all of the machines in question are IEEE. The
preprocessor symbols I mentionned have been around since C90,
however, and are pretty much universally supported. (The also
permit testing for other formats, in case you only want to
support IBM format. Or for something like:

#if FLT_RADIX == 2 && FLT_MANT_DIG == 24 && ...
// IEEE implementation
#elif FLT_RADIX == 16 && FLT_MANT_DIG == 6 && ...
// IBM implementation
#else
#error floating point format not yet supported
#endif

I'd do this very differently, of course. Something more like:

#include GB_dependentInclude(floatingpoint,gb/whatever.cc)

with the various implementations in separate source files, in
different directories. Conditional compilation is an anathema
for maintenance, and should generally be avoided.
 
R

Richard Herring

In message
On 2008-03-19 11:49, James Kanze wrote:
[...]
There are a number of useful values in either <cfloat> or
<limits>. Those in <cfloat> are macros which evaluate to
constant expressions, which when integral can be used in the
preprocessor, e.g. for conditional compilation. (The ones that
would interest you here are xxx_RADIX, xxx_MANT_DIG, xxx_MIN_EXP
and xxx_MAX_EXP, where xxx is one of FLT, DBL OR LDBL.)
Or one can mandate IEEE 754 (also known as IEC 559) by using
the is_iec559() function of the numeric_limits class. Combine
this with sizeof() and all you have to worry about is
endianess issues (which you might be able to solve using
ntohl() in POSIX).

But that's runtime, and not compile time.

In C99 (and in C++0x?), you can test whether __STDC_IEC_559__ is
defined. In practice, however, of the five compilers I have
ready access too (VC++ and g++ under Windows, g++ under Linux,
and g++ and Sun CC under Solaris), only g++ under Linux tests
true, although all of the machines in question are IEEE. The
preprocessor symbols I mentionned have been around since C90,
however, and are pretty much universally supported. (The also
permit testing for other formats, in case you only want to
support IBM format. Or for something like:

#if FLT_RADIX == 2 && FLT_MANT_DIG == 24 && ...
// IEEE implementation

You'd need to test a lot more than just those two macros, of course.
FLT_RADIX == 2 && FLT_MANT_DIG == 24 would also match VAX-11 F_floating,
even though its representation and semantics are quite different from
IEEE.
 
J

James Kanze

In message
James Kanze <[email protected]> writes

[...]
You'd need to test a lot more than just those two macros, of
course. FLT_RADIX == 2 && FLT_MANT_DIG == 24 would also match
VAX-11 F_floating, even though its representation and
semantics are quite different from IEEE.

Agreed. That's why I left the ... At least some tests with
FLT_MIN_EXP and FLT_MAX_EXP would necessary.
 

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

No members online now.

Forum statistics

Threads
474,176
Messages
2,570,947
Members
47,498
Latest member
log5Sshell/alfa5

Latest Threads

Top