Topic: Floating point hex constants


Author: j.kewley@dl.ac.uk (John Kewley)
Date: Wed, 19 Oct 2005 05:20:48 GMT
Raw View
[Sorry if something of this ilk has been posted previously]

I was bemused by the latest C (and I think also now C++) standard ways
of writing hex fractional constants. Does anyone know how this
convention came about? I'll try and explain my confusion below:

We all know about decimal notation in C(++):

ABC.DEFeGH = A*10^2 + B*10^1 + C*10^0 + D*10^-1 ... * 10^GH

Note the use of the radix 10 throughout and decimal digits throughout

Note the equivalence:
A.BeX = AB.0e(X-1) = 0.ABe(X+1)

Exercise 1:
What does 0x9p1 represent?
9.0
90.0
0x90.0
0x18.0
18.0
0x12.0
144.0
0.0
undefined

Here is how it goes:

Take a hex fractional constant:

0xABC.DEFpGH

Firsly note that ABC and DEF are hex digits while G and H are decimal
digits.

Secondly, note that p means x2^ not x16^

so the above equals
A*16^2 + C*16^1 + C*16^0 + D*16^-1 ... * 2^GH

and my answer to Exercise 1 is
18.0, 1.8e1 or 0x12.0

(at least according to myunderstanding)

What I had expected was to find hex digits for exponent and the exponent
  representing a multiple of 16 not 2.

I dislike this for the following reasons:
1. It would be more consistent if all digits were hex
2. It would be better if exponent represented multiplying by the base
    (ie 16)
3. The equivalence above does not hold
4. mixed radices - a base 16 number multiplied by a decimal power of 2
    radix soup anyone?

Any ideas where this came from? Is there a reason for what to me appears
a strange way of defining things? Is there historical precedent?

As a final exercise for the student:

Which of following are legal and what are they in decimal format:
0x1f, 0x1.0f, 0x1.0fe0, 0x1.0e0f

i.e. watch out for trailing f - is it an f suffix, or a valid hex digit.

JK

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: sgganesh@gmail.com
Date: Wed, 19 Oct 2005 21:16:53 CST
Raw View
>> I was bemused by the latest C (and I think also now C++) standard ways
>> of writing hex fractional constants.
In C99 grammar I could see binary-exponent-part, but not in Standard
C++ (1998) + TC1 (2003), so I dont think its yet supported in the
Standard:

hexadecimal-floating-constant:
            hexadecimal-prefix hexadecimal-fractional-constant
binary-exponent-part floating-suffixopt
            hexadecimal-prefix hexadecimal-digit-sequence
binary-exponent-part floating-suffixopt

binary-exponent-part:
          p signopt digit-sequence
          P signopt digit-sequence

I do think its a very useful construct; instead of calculating a
fraction, something like, 1.19209E-07 and lose precision for my
paltform for representing a small value like this, I can use concise
notation as 0X1P-23F.

Still my related complaint is that C99/C++98 doesn't support binary
constants or ability to directly read or write binary numbers (or does
it already?/some proposal already made?). I've faced the need many
times and found it disappointing to hand-code such trivial things again
and again.

Thanks!
-Ganesh

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nagle@animats.com (John Nagle)
Date: Thu, 20 Oct 2005 02:22:09 GMT
Raw View
John Kewley wrote:


> Take a hex fractional constant:
>
> 0xABC.DEFpGH
>
> Firsly note that ABC and DEF are hex digits while G and H are decimal
> digits.

    That was a wierd decision.  Why was it done that way?

> Secondly, note that p means x2^ not x16^

    That's the right decision.  With a binary exponent,
you can directly represent all normalized floating point numbers
in this hex notation.  That is, all nonzero floating point
numbers can be represented in a form where
the number before the radix point is 0, and the
number after the radix point is between 8 and f.
The exponent from the floating point internal representation
becomes the exponent in the text representation, assuming
an IEEE-type floating point format.  So there's a simple, direct,
and exact translation from internal to external floating point
format.  Which is the whole point of hex floats.

    IBM mainframes actually do use base 16 exponents,
but this is generally considered to be numerically
undesirable.  It probably saved some components when
that decision was made in 1955 for IBM's 7030 computer
(the STRETCH) and was carried forward into the IBM/360
line, where it lives on.

    By the way, are hex floats standardized for I/O?

   John Nagle

>
> so the above equals
> A*16^2 + C*16^1 + C*16^0 + D*16^-1 ... * 2^GH
>
> and my answer to Exercise 1 is
> 18.0, 1.8e1 or 0x12.0
>
> (at least according to myunderstanding)
>
> What I had expected was to find hex digits for exponent and the exponent
>  representing a multiple of 16 not 2.
>
> I dislike this for the following reasons:
> 1. It would be more consistent if all digits were hex
> 2. It would be better if exponent represented multiplying by the base
>    (ie 16)
> 3. The equivalence above does not hold
> 4. mixed radices - a base 16 number multiplied by a decimal power of 2
>    radix soup anyone?
>
> Any ideas where this came from? Is there a reason for what to me appears
> a strange way of defining things? Is there historical precedent?
>
> As a final exercise for the student:
>
> Which of following are legal and what are they in decimal format:
> 0x1f, 0x1.0f, 0x1.0fe0, 0x1.0e0f
>
> i.e. watch out for trailing f - is it an f suffix, or a valid hex digit.
>
> JK
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]
>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: usenet-nospam@nmhq.net (Niklas Matthies)
Date: Thu, 20 Oct 2005 04:42:08 GMT
Raw View
On 2005-10-20 02:22, John Nagle wrote:
> John Kewley wrote:
:
>> Take a hex fractional constant:
>>
>> 0xABC.DEFpGH
>>
>> Firsly note that ABC and DEF are hex digits while G and H are
>> decimal digits.
>
>     That was a wierd decision.

It's not that weird, unless you find e.g. 0xFFFFul << 16 weird.

> Why was it done that way?

One reason is that it would make the float suffix f/F ambiguous.
(That's also the reason why the exponent part is required for
hexadecimal floating constants). Another reason is that the benefit
of having a hexadecimal notation for the mantissa (no rounding to
binary representations) does not apply to the exponent.

-- Niklas Matthies

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: walter@nospamm-digitalmars.com ("Walter Bright")
Date: Fri, 21 Oct 2005 05:26:18 GMT
Raw View
<sgganesh@gmail.com> wrote in message
news:1129715045.221983.9140@g49g2000cwa.googlegroups.com...

> In C99 grammar I could see binary-exponent-part, but not in Standard
> C++ (1998) + TC1 (2003), so I dont think its yet supported in the
> Standard:

No, but many C++ compilers, such as the Digital Mars C++, support hex
floating point constants as an extension (and has since 1990 or so <g>; hex
floats came from the old Numerical C Extensions Group).

> I do think its a very useful construct; instead of calculating a
> fraction, something like, 1.19209E-07 and lose precision for my
> paltform for representing a small value like this, I can use concise
> notation as 0X1P-23F.

Hex floats are very handy when one is preparing exact values, such as
coefficients for a polynomial. It can sometimes be very difficult to come up
with a decimal fraction that, with rounding, produces the exact bit pattern
desired, as well as dealing with the vagaries of a compiler's internal
string-to-float conversion.

Also, as you pointed out, header files like <float.h> wind up being a lot
simpler:

#define FLT_EPSILON     0x1p-23

It's a lot easier to visually verify that 0x1p-23 is correct than carefully
going over 1.19209290e-7f and looking for missing or transposed digits, or
wrestling with a compiler that just won't give you exactly the right bit
pattern.

-Walter Bright
www.digitalmars.com C, C++, D programming language compilers


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]