hex and octal constants in various languages

G

Guest

LC's No-Spam Newsreading account wrote:
Even less likely to work than REAL. Again TRANSFER is a good
solution. Though there is no guarantee that a default integer is four
characters long.

It is in practice in my case, and in all the environments I can
realistically work. No longer the time of 36-bit machines ...
< In Java I tried
Look at the FloatToIntBits and IntToFloatBits functions.

f = Float.intBitsToFloat( 0x3f800000 );
as another poster suggested. Thanks to both !
Why is the result not expected? You are assigning an integer
constant to a float variable.

Well, my reference for Java is the tutorial on the java.sun.com site and
I've never found a CLEAR statement that an hex pattern is necessarily
typed as an integer. I assumed it to be an arbitrary bit pattern, which
could be reversed into any type of variable.
 
G

Guest

float x = 0x3.f8p-2f;

I tried to play with this form, e.g.

f=0X1.ap0f; /* 1.625 */
f=0X1.ap1f; /* 3.25 */
f=0X1.ap-1f; /* 0.8125 */

But it is not obvious to me what the two parts are ... mantissa in hex
and exponent as power of 2 in decimal ... but are they the same that
constitute exactly the IEEE representation or can be scaled arbitrarily ?
 
G

Guest

For heaven's sake read up on the syntax rather than trying to guess
it.

I've bookmarked your links, but I did read what available in the
java.sun.com tutorial and the API documentation (well, to find something
in the API documentation you have to know what to look already).

As said in other posts, my (wrong) assumption was that an hex "string"
like 0X40800000 would be just an arbitrary bit pattern which can be
transferred into any variable type, not an integer constant. I've never
encountered explicitly such definition. NOW I know.
 
G

Guest

The problems with the "%o" and "%X" format specifiers in this case are
technically exactly the same as in the previous two cases. However,

Hmm... what's then the "standard" way to obtain an hex dump of a float
(in the way the Z format will do in Fortran), other than writing it to a
binary file and using od :) ?

I tried the above using one of the following instead of "somevalue"
(with gcc)

f=1.0f ; /* gives 3FF00000 instead of 3F800000 */
f=2.0f ; /* gives 40000000 */
f=4.0f ; /* gives 40800000 instead of 40100000 */
f=8.0f ; /* gives 41000000 instead of 40200000 */
C FORTRAN

For 2.0 I obtain the same binary representation I obtain in Fortran, for
the other values (note all powers of 2) I obtain discrepant values. 'm
pretty sure (checked with my old Excel spreadsheet doing the bit-by-bit
display of a real in IEEE and VAX form) the Fortran value is the correct
one (IEEE).

Is this a side effect of some signed vs unsigned thing ?
 
M

markspace

LC's No-Spam Newsreading account said:
Hmm... what's then the "standard" way to obtain an hex dump of a float
(in the way the Z format will do in Fortran), other than writing it to a
binary file and using od :) ?

I'd do something like this (warning, been too long since C for me):

union float_int {
float f;
int i;
} x;

x.f = 1.0f;
printf( "%08.8X", x.i );
 
B

Ben Bacarisse

LC's No-Spam Newsreading account said:
I tried to play with this form, e.g.

f=0X1.ap0f; /* 1.625 */
f=0X1.ap1f; /* 3.25 */
f=0X1.ap-1f; /* 0.8125 */

But it is not obvious to me what the two parts are ... mantissa in hex
and exponent as power of 2 in decimal ... but are they the same that
constitute exactly the IEEE representation or can be scaled
arbitrarily ?

The bit before the p just gives the value as a hexadecimal fraction;
the bit after the p gives the exponent. This is much more useful than
tying the notation to one specific representation of floating point
numbers. Here are your example numbers in binary rather than hex:

1.101 = 1+1/2+1/8 = 1.625
11.01 = 2+1+1/4 = 3.25
0.1101 = 1/2+1/4+1/16 = 0.8125
 
M

markspace

LC's No-Spam Newsreading account said:
Well, my reference for Java is the tutorial on the java.sun.com site and
I've never found a CLEAR statement that an hex pattern is necessarily
typed as an integer. I assumed it to be an arbitrary bit pattern, which
could be reversed into any type of variable.


You need a few more references. The tutorial is just that, a tutorial.
It doesn't cover everything. However it's not hard to type "Java
integer hex" into Google and get some additional tutorials, some of
which do talk about hex literal constants.

The ultimate source is the JLS:

<http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.10.1>

Scroll down about one page to where it says "HexNumeral" which is where
you can see that the "0x" format is for integers.

Floating point hex numbers are available too. Scroll down a bit more to
the section on floating point literals. (The important difference
between hex integers and hex floats is that hex floats have a decimal
point: 0xAA.55)

But those hex floats are still *NUMBERS*, not *BIT PATTERNS*. Use the
Float methods intToFloatBits and floatToIntBits to access floats as bit
patterns.
 
B

Ben Bacarisse

LC's No-Spam Newsreading account said:
Hmm... what's then the "standard" way to obtain an hex dump of a float
(in the way the Z format will do in Fortran), other than writing it to
a binary file and using od :) ?

for (int b = 0; i < sizeof(float); i++)
printf("%02x", ((unsigned char *)&f));

but there is no shorthand for this because it is not needed much. Any
actual dump of the representation will have to interpreted depending
on the internal format being used.

People want hex output in order to find out exactly what value is in a
float without worrying about the effect of conversion to decimal. C
can do this more useful operation directly using the format %a (or %A).

Of course, if the machine uses decimal floating point, %f, %e and %g
give you the exact values and %a will make matters worse.
I tried the above using one of the following instead of "somevalue"
(with gcc)

f=1.0f ; /* gives 3FF00000 instead of 3F800000 */
f=2.0f ; /* gives 40000000 */
f=4.0f ; /* gives 40800000 instead of 40100000 */
f=8.0f ; /* gives 41000000 instead of 40200000 */
C FORTRAN

For 2.0 I obtain the same binary representation I obtain in Fortran,
for the other values (note all powers of 2) I obtain discrepant
values. 'm pretty sure (checked with my old Excel spreadsheet doing
the bit-by-bit
display of a real in IEEE and VAX form) the Fortran value is the
correct one (IEEE).

Is this a side effect of some signed vs unsigned thing ?

Output from a program that "breaks the rules" is unreliable. Your
code has undefined behaviour. One might speculate on what comes out,
but you'd be better off avoiding undefined behaviour.
 
M

markspace

LC's No-Spam Newsreading account said:
- There may be means to store an hex constant
into a float like Float.intBitsToFloat in Java


For Java, these MUST be present. It's required, at least for Java SE
(as opposed to Java ME, which I think is still back on the 1.0 API).
- it is not obvious to find the relevant information in the
documentation :-(


Google key words, click on and read each page linked on the first
results page. This usually works for me, and did for "java tutorial hex."

The union keyword for C is a bit trickier to find. However, making a
union of float and int is usually the first elementary example presented
when talking about union, so if you had read your text you would have
seen it. So the answer here is to read ALL the documentation, not just
some of it. And for C I think a book like Kerrigan and Ritchie is a
rather short read, not hard at all.
 
N

Nick Keighley

Hmm... what's then the "standard" way to obtain an hex dump of a float
(in the way the Z format will do in Fortran), other than writing it to a
binary file and using od :) ?

I tried the above using one of the following instead of "somevalue"
(with gcc)

     f=1.0f ;  /* gives 3FF00000 instead of 3F800000 */
     f=2.0f ;  /* gives 40000000                     */
     f=4.0f ;  /* gives 40800000 instead of 40100000 */
     f=8.0f ;  /* gives 41000000 instead of 40200000 */
                        C                   FORTRAN

For 2.0 I obtain the same binary representation I obtain in Fortran, for
the other values (note all powers of 2) I obtain discrepant values. 'm
pretty sure (checked with my old Excel spreadsheet doing the bit-by-bit
display of a real in IEEE and VAX form) the Fortran value is the correct
one (IEEE).

Is this a side effect of some signed vs unsigned thing ?

I tried this

#include <stdio.h>

void dump_val (unsigned char *p, size_t n)
{
size_t i;
for (i = 0; i < n; i++)
printf ("%.02x ", p & 0xff);
printf ("\n");
}

void dump_double (double x)
{
unsigned char *p;
p = (unsigned char*)&x;
printf ("representation of %f is ", x);
dump_val (p, sizeof(x));}

int main (void)
{

dump_double (1.0);
dump_double (2.0);
dump_double (4.0);
dump_double (8.0);

return 0;
}

and got

representation of 1.000000 is 00 00 00 00 00 00 f0 3f
representation of 2.000000 is 00 00 00 00 00 00 00 40
representation of 4.000000 is 00 00 00 00 00 00 10 40
representation of 8.000000 is 00 00 00 00 00 00 20 40

are you sure about 1.0?

[note: an earlier version of this program posted here
just repeatedly printed the first byte]
 
N

Nick Keighley

LC's No-Spam Newsreading account wrote:




I'd do something like this (warning, been too long since C for me):

   union float_int {
     float f;
     int i;
   } x;

   x.f = 1.0f;
   printf( "%08.8X", x.i );

and if a float won't fit in an int?
 
J

James Kuyper

LC's No-Spam Newsreading account said:
I thought they were "universal" like O and Z in Fortran.

Did the documentation for those specifiers give you any justification
for such thinking? It should say something like the following: "The
unsigned int argument is converted to unsigned octal (o), unsigned
decimal (u), or unsigned hexadecimal notation (x or X)... "
(7.19.6.1p8). Note, in particular, that if the argument is not an
unsigned int, this description is meaningless, which is a strong hint
that the argument has to be an unsigned int.

....
I wasn't aware of this. See above.


Expecting an universal edit descriptor, I expected that a 2-byte
quantity resulted in 4 hex digits.

I recommend learning a lot more about C, and in particular being more
careful to read the available documentation or textbooks, before forming
any more expectations about what C code will do. You're misinterpreting
some very elementary issues.
because that's the internal representation of the float 4.0 in IEEE
(just re-checked with my old Excel spreadsheet which gives the internal
representation of IEEE and VAX floats). ...

But did anyone tell you anything to suggest that the assignment operator
had any effect other than setting the left operand to represent as
closely as possible the save value as the right operand? In particular,
did anyone ever suggest to you that the assignment operator would set
the representation of the left operand, rather than the value it
represents, to match the right operand?
... I assumed that an "hex constant"
was just a bit pattern, with no type implied.

No, a hex constant is just one of many different ways of writing an
integer constant. In C, an integer constant of 127 can be written as
127, 0x3F, 0177, '\x3f', or '\0177'. Any of the first three can be
followed by 'u', indicating unsigned, or by 'l', indicating a long int.
All of the letters given above (x, u, l, and the hex digits a, b, c, d,
e, and f) can be either upper or lower case.
I realize now that, at least in C, hex constants are integer constants
(is this implicit or documented ?)

It's documented very clearly in section 6.4.4 of the standard.
 
J

James Kuyper

LC's No-Spam Newsreading account said:
Hmm... what's then the "standard" way to obtain an hex dump of a float
(in the way the Z format will do in Fortran), other than writing it to a
binary file and using od :) ?

unsigned char *p = (unsigned char*)&f;
unsigned char *lim = p + sizeof f;

printf("%13.7g 0X", f);
while(p < limit)
printf("%02X", *p++);
printf("%zu\n", sizeof f);

Note: if you're using C90, replace that last line with:

printf("%lu\n", (unsigned long)sizeof f);

Note that this will not work as intended if UCHAR_MAX > 255. Writing the
code so that it will work properly for arbitrary values of UCHAR_MAX is
quite feasible, but it would add significantly to the complexity of the
code, which I think would only add to your confusion; since such systems
are rare, I kept the code simple by not dealing with them.
I tried the above using one of the following instead of "somevalue"
(with gcc)

f=1.0f ; /* gives 3FF00000 instead of 3F800000 */
f=2.0f ; /* gives 40000000 */
f=4.0f ; /* gives 40800000 instead of 40100000 */
f=8.0f ; /* gives 41000000 instead of 40200000 */
C FORTRAN

For 2.0 I obtain the same binary representation I obtain in Fortran, for
the other values (note all powers of 2) I obtain discrepant values. 'm
pretty sure (checked with my old Excel spreadsheet doing the bit-by-bit
display of a real in IEEE and VAX form) the Fortran value is the correct
one (IEEE).

Is this a side effect of some signed vs unsigned thing ?

Since the printf() call that you wrote has undefined behavior, there's
really nothing that can meaningfully be said about why you got the
results that you got.
 
M

markspace

Nick said:
and if a float won't fit in an int?

Goes 'splody. If you're up against platform dependencies (which you
will be in the real world), you might have to resort to #if

#if sizeof(int) == 4
#define INT4 int
#endif

#if sizeof(long) == 8
#define INT8 long
#endif

And lots more like that. These sorts of things are needed for dealing
with IO and external file formats, ime.

Then go:

union float_int {
FLOAT4 f;
INT4 i;
} x;

Which will meet the op's request for 4 byte values.
 
J

James Kuyper

markspace said:
I'd do something like this (warning, been too long since C for me):

union float_int {
float f;
int i;
} x;

x.f = 1.0f;
printf( "%08.8X", x.i );

That code is problematic for several different reasons: it reads the
value of a different member of a union than the one last written, it
reads the value of an 'int' object that might contain a trap
representation, and it passes an int value to a printf() call when
corresponding specifier is "%X". If sizeof(int) > sizeof(float), all of
those problems just got worse.

Even if none of the above issues apply, if sizeof(int) < sizeof(float),
or if 'int' has any padding bits, this code will not print the entire
representation, and the result you get will depend upon the byte order
of 'int'. I say "byte order" rather than endianess because it's possible
that sizeof int > 2, in which case there's many more possibilities than
just those two. I once saw a list identifying 12 of the 24 possible byte
ordering for 4-byte integers as being in current use, though there's
only 4 that are at all common.
 
R

robin

LC's No-Spam Newsreading account said:
I am collecting a sort of phrase books with equivalent "things" in
various languages.

I am now considering the indication of constants as hex, oct or binary
constants.

PL/I constants:

bit constant '1011100'b
bit data hex constant: '3ABC'B4
character hex constant '2E59'X
binary constant 10111001b
binary hex constant '48AB'XN
 
D

Dik T. Winter

> f=1.0f ; /* gives 3FF00000 instead of 3F800000 */
> f=2.0f ; /* gives 40000000 */
> f=4.0f ; /* gives 40800000 instead of 40100000 */
> f=8.0f ; /* gives 41000000 instead of 40200000 */
> C FORTRAN
>
> For 2.0 I obtain the same binary representation I obtain in Fortran, for
> the other values (note all powers of 2) I obtain discrepant values.

The first column contains the hex representations of single precision
floating-point, the second the hex representations of double precision
floating-point with the last eight hex digits chopped off (they are all 0).

I think that you obtained the first column from Fortran and the seconde
from C, contrary to what you state. And the second is expected from C,
as in printf the float argument is automatically converted to double.
 
R

Richard Maine

But reading Metcalf, Reid and Cohen (Fortran 95/2003 explained) I got
the impression they were standardized NOW.

They are, but...
What is exactly non standard in my usage ?

- usage of hex constants in assignments instead of DATA ?
- usage of hex constants for non-integers ?
- usage of hex edit descriptor for non-integers ?

Yes. All 3 of those. F2003 allows a few other places, but they are still
pretty limitted. Other posts have mentioned the reasons. In particular,
f2003 allows them as arguments to the real and integer intrinsics. That
provides a standard way to use them in assignments and for reals.
I'd better revert to my old usages and consider hex constants as
something to avoid.

They are ok with the above limitations.
Well, unless one has access to The Standard Itself, the only way one can
gain experience is testing with specific compilers

That is a severe overstatement at best. While textbooks are not
definitive in cases of disagreement of interpretation, they are
excellent sources for most people - probably better than the standard
itself in that they are usually easier to read. You mention Metcalf,
Reid, and Cohen above. That's a fine source - certainly far better than
just testing with a compiler.

Testing with a specific compiler is simply a horrible way to evaluate
standard conformance. I cannot count the number of times that point has
been reiterated in this forum, usually when someone cites the fact that
their code compiled as evidence that it must be ok (and they are wrong).
There are many, many things that realistically cannot be diagnosed by a
compiler. Testing with a compiler is a useful "sanity check" to help see
if you might have overlooked something, but that is only a backup, not
the primary source.

At the very least, be sure to turn on the compiler's switches for
diagnosing standard conformance. The Intel compiler (and those in its
heritage) is particularly notable for accepting large numbers of
nonstandard features without warning by default. I consider this a
shortcoming of that mostly decent compiler. But the compiler does have a
switch for diagnosing the use of many of those nonstandard forms.
Without using that switch, I can't regard testing with the compiler as
much more than a joke in terms of verifying standard conformance. With
the switch, it is probably as good as most other compilers. I expected
that it would probably disgnose these particular errors. But as noted
above, a compiler can never be very good.
 
R

Richard Maine

LC's No-Spam Newsreading account said:
I thought they were "universal" like O and Z in Fortran.

You mean like the O and Z edit descriptor in Fortran are *NOT*? They
allow only integers in standard Fortran.
I realize now that, at least in C, hex constants are integer constants
(is this implicit or documented ?)

Again, just like in Fortran. Yes, this is documented.
 

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
473,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top