[comp.lang.c] Here's a challenge for floating point lovers.

Ray Butterworth <rbutterworth@watdragon.waterloo.edu> (01/22/91)

Ever tried to come up with a manifest for a specific floating point value?
It is next to impossible.

For instance, using knowledge of what the bits look like,
#define MAXFLOAT  (*(double*)"\377\177\377\377\377\377\377\377")
works on vaxes, but it makes really disgusting assumptions about the
alignment of string constants and doubles.

But, if we assign that value to a variable, print out the result,
and then enter that result into a header file, when it gets
processed again the value is wrong.  For instance:

Stock "cc" command gives:
                      true max  ff7fffffffffffff  1.70141183460469229000e+38
       1.70141183460469229e+38  ff7ffffffffffdff  1.70141183460469225000e+38
   4096*4.15383748682786209e34  ff7ffffffffffeff  1.70141183460469227000e+38

"gcc" command gives:
                      true max  ff7fffffffffffff  1.70141183460469229000e+38
       1.70141183460469229e+38  ff7ffffffffffeff  1.70141183460469227000e+38
   4096*4.15383748682786209e34  ff7fffffffffffff  1.70141183460469229000e+38

So, simply using the output value is wrong on GCC and twice as bad on CC.
Using "4096*4.15383748682786209e34" works with GCC, but not with CC.
In fact, I haven't found a constant that will work with CC other than
the kludgy mess with the (double*), which will cause hardware faults
on many (non-vax) machines.

Anyone know how to solve this problem in general,
or even in this specific case?

Does ANSI X3.159 require the ability to define such a constant?

Here's the program that produced the above:

#include <stdio.h>

#define MAXFLOAT  (*(double*)"\377\177\377\377\377\377\377\377")

	static void
test(label, value)
	char *label;
	double value;
{
	auto int index;

	printf("%30s  ", label);
	for (index=0; index<sizeof(value); ++index)
		printf("%2.2x", index[(unsigned char*)&value]);
	printf("  %25.20e\n", value);
}



main() {
	auto double max = MAXFLOAT;

	test("true max", max);
	test("1.70141183460469229e+38", 1.70141183460469229e+38);
	test("4096*4.15383748682786209e34", 4096*4.15383748682786209e34);
}

henry@zoo.toronto.edu (Henry Spencer) (01/23/91)

In article <1991Jan21.215629.8393@watdragon.waterloo.edu> Ray Butterworth <rbutterworth@watdragon.waterloo.edu> writes:
>Ever tried to come up with a manifest for a specific floating point value?
> ...
>Does ANSI X3.159 require the ability to define such a constant?

No.  Nobody's come up with a good way of doing this that I know of,
especially when portability is desired.

My dim recollection (references aren't handy) is that systems conforming
to the IEEE floating-point standard are required to provide string<->number
conversions that are sufficiently well-behaved that you can rely on the
exact results, if you do them right.
-- 
If the Space Shuttle was the answer,   | Henry Spencer at U of Toronto Zoology
what was the question?                 |  henry@zoo.toronto.edu   utzoo!henry

gwyn@smoke.brl.mil (Doug Gwyn) (01/24/91)

In article <1991Jan22.180927.29232@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
>>Does ANSI X3.159 require the ability to define such a constant?
>No.  Nobody's come up with a good way of doing this that I know of,
>especially when portability is desired.

Presumably portability is not an issue for this application.  What some
implementors do is to initialize what amounts to a union type with the
proper bits then refer to the floating-point member of that union to get
the value interpreted properly with the proper floating type.  The
standard does NOT require that the values of the <float.h> macros be
CONSTANT expressions; in particular they may access external storage at
run time (contents of such a union, for example).  Note also that this
means that FLT_RADIX and other <float.h> macros must not be used in #if
expressions in strictly conforming programs.

volpe@camelback.crd.ge.com (Christopher R Volpe) (01/24/91)

In article <14938@smoke.brl.mil>, gwyn@smoke.brl.mil (Doug Gwyn) writes:
|>The
|>standard does NOT require that the values of the <float.h> macros be
|>CONSTANT expressions; in particular they may access external storage at
|>run time (contents of such a union, for example).  Note also that this
|>means that FLT_RADIX and other <float.h> macros must not be used in #if
|>expressions in strictly conforming programs.
  
2.2.4.2.2:
  Of the values in the <float.h> header, FLT_RADIX shall be a constant
expression suitable for use in #if preprocessing directives; all other
values need not be constant expressions.            
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com

gwyn@smoke.brl.mil (Doug Gwyn) (01/24/91)

In article <16035@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com (Christopher R Volpe) writes:
-In article <14938@smoke.brl.mil>, gwyn@smoke.brl.mil (Doug Gwyn) writes:
-|>standard does NOT require that the values of the <float.h> macros be
-|>CONSTANT expressions; ...
-2.2.4.2.2:
-  Of the values in the <float.h> header, FLT_RADIX shall be a constant
-expression suitable for use in #if preprocessing directives; all other
-values need not be constant expressions.            

Oops, I missed that; thanks for the correction.  FLT_RADIX then is okay
for use in #if expressions, but the other <float.h> macros aren't, not
even FLT_ROUNDS.

sarima@tdatirv.UUCP (Stanley Friesen) (01/26/91)

In article <14964@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>Oops, I missed that; thanks for the correction.  FLT_RADIX then is okay
>for use in #if expressions, but the other <float.h> macros aren't, not
>even FLT_ROUNDS.

To emphasize this point, I had occasion to look at float.h for SysVr4
a bit ago and it defined FLT_ROUNDS as follows:

#define FLT_ROUNDS (__flt_rounds)

(At least if __STDC__ is defined as 1)

So, there exists an ANSI compliant C compiler that in fact
makes use of this permission for a non-constant float expression.
-- 
---------------
uunet!tdatirv!sarima				(Stanley Friesen)

dik@cwi.nl (Dik T. Winter) (01/26/91)

In article <101@tdatirv.UUCP> sarima@tdatirv.UUCP (Stanley Friesen) writes:
 > In article <14964@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
 > >Oops, I missed that; thanks for the correction.  FLT_RADIX then is okay
 > >for use in #if expressions, but the other <float.h> macros aren't, not
 > >even FLT_ROUNDS.
 > 
 > #define FLT_ROUNDS (__flt_rounds)
 > So, there exists an ANSI compliant C compiler that in fact
 > makes use of this permission for a non-constant float expression.

And right they are because it can change at runtime.
--
dik t. winter, cwi, amsterdam, nederland
dik@cwi.nl

gwyn@smoke.brl.mil (Doug Gwyn) (01/27/91)

In article <2855@charon.cwi.nl> dik@cwi.nl (Dik T. Winter) writes:
>In article <101@tdatirv.UUCP> sarima@tdatirv.UUCP (Stanley Friesen) writes:
> > #define FLT_ROUNDS (__flt_rounds)
>And right they are because it can change at runtime.

However, the C standard does not contemplate rounding mode changing
during execution of a strictly conforming program.  That stuff is
an IEEE floating-point extension that need not be supported by a
conforming implementation.  (I'm trying to resist my usual slam at
IEEE floating point.)

greywolf@unisoft.UUCP (The Grey Wolf) (01/29/91)

[ .comm		_newsfood, 4; ]

(Apologies for the apparent waste of bandwidth...)

Doug, I can't find another host besides "gould" who can talk to you
to send mail, so...

In article <14993@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes: 
>
>(I'm trying to resist my usual slam at IEEE floating point.)
>

How many different floating point formats are there out there?  I'm
aware of IEEE and VAX.  Are there any others, and what are the pros and
cons?

I can only assume that somehow IEEE is drain-bamaged; whether by loss of
precision or what, I don't know.

-- 
thought:  I ain't so damb dumn!
war: Invalid argument
...!{ucbvax,acad,uunet,amdahl,pyramid}!unisoft!greywolf

henry@zoo.toronto.edu (Henry Spencer) (01/30/91)

In article <3322@unisoft.UUCP> greywolf@unisoft.UUCP (The Grey Wolf) writes:
>How many different floating point formats are there out there?  I'm
>aware of IEEE and VAX.  Are there any others, and what are the pros and
>cons?

There are lots of them.  Even on the VAX there are two generations of
incompatible formats -- the original ones were pdp11-compatible, while
the later ones improved on that.  In the days before IEEE format, every
manufacturer had his own, and often more than one.  You can find the
occasional floating-point chip that can speak three or four different
formats on request.

In general, despite Doug's distaste for its complexity, IEEE floating
point is an order of magnitude superior to the rest.  It was designed
by people who understood numerical arithmetic.  That may sound obvious,
but the fact is that a lot of the older formats were designed more for
hardware convenience than for good numerical properties.

Nobody (well, except maybe Seymour Cray, who has other constraints
to think about) designs new machines using anything other than IEEE.
-- 
If the Space Shuttle was the answer,   | Henry Spencer at U of Toronto Zoology
what was the question?                 |  henry@zoo.toronto.edu   utzoo!henry

gwyn@smoke.brl.mil (Doug Gwyn) (01/30/91)

In article <3322@unisoft.UUCP> greywolf@unisoft.UUCP (The Grey Wolf) writes:
>How many different floating point formats are there out there?

There are many.  IBM mainframes use a base-16 representation, and Gould
PowerNodes have a similar if not identical representation.  Other long-
established mainframes tend to have other floating formats.  Even among
IEEE implementations, there are several variations.

>I can only assume that somehow IEEE is drain-bamaged; whether by loss of
>precision or what, I don't know.

There are several problems with IEEE floating point.  The model of
"negative infinity", "signed zero", etc. is not mathematically correct,
and programs that rely on such non-numbers can silently produce incorrect
results.  The deficiency that is relevant for our original discussion is
that the IEEE standard envisions programs actually dealing with, nay,
HAVING to deal with, detailed aspects of the model such as rounding modes.
This is utterly inappropriate for visibility at a higher-level language
such as Fortran, Pascal, Modula II, C, Ada, etc. where what is desired is
that the language implementation provide a single consistent model for
floating-point (approximate real-number) operations.  We had one heck of
a time trying to adjust the standard C library math function specifications
to accommodate the weird behavior of IEEE f.p. implementations.

bruce@seismo.gps.caltech.edu (Bruce Worden) (01/30/91)

henry@zoo.toronto.edu (Henry Spencer) writes:
>Nobody (well, except maybe Seymour Cray, who has other constraints
>to think about) designs new machines using anything other than IEEE.

As I hear it, Seymour has little elves telling him what to do.  

>In general, despite [Doug Gwyn's] distaste for [IEEE's] complexity [ ... ]

Hmmm, interesting.  Do you suppose that Doug is actually an elf?

Disclaimer: No offense, Doug, just a joke.
--------------------------------------------------------------------------
C. Bruce Worden                            bruce@seismo.gps.caltech.edu
252-21 Seismological Laboratory, Caltech, Pasadena, CA 91125

richard@aiai.ed.ac.uk (Richard Tobin) (01/30/91)

In article <1991Jan29.233352.24087@nntp-server.caltech.edu> bruce@seismo.gps.caltech.edu (Bruce Worden) writes:
>Hmmm, interesting.  Do you suppose that Doug is actually an elf?

No, you have him mixed up with Chris Torek.

-- Richard
-- 
Richard Tobin,                       JANET: R.Tobin@uk.ac.ed             
AI Applications Institute,           ARPA:  R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk
Edinburgh University.                UUCP:  ...!ukc!ed.ac.uk!R.Tobin

gwyn@smoke.brl.mil (Doug Gwyn) (01/31/91)

In article <1991Jan29.233352.24087@nntp-server.caltech.edu> bruce@seismo.gps.caltech.edu (Bruce Worden) writes:
>Hmmm, interesting.  Do you suppose that Doug is actually an elf?
>Disclaimer: No offense, Doug, just a joke.

Ho, ho, ho.  Just see if YOU get any presents next Christmas!

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (02/01/91)

In article <1991Jan21.215629.8393@watdragon.waterloo.edu>, rbutterworth@watdragon.waterloo.edu (Ray Butterworth) writes:
> Ever tried to come up with a manifest for a specific floating point value?
> Anyone know how to solve this problem in general,

There are several answers.  One is that this is why "hex floats" are being
considered as an extension.

Here is a method for generating any floating-point value you want
*provided* that the machine's floating-point arithmetic uses a power of
2 as its radix, that converting small integers to floating point is
exact, that scaling is exact, and that addition is exact when it can be.

1. Figure out what bit pattern you want.
2. Divide it into convenient chunks, say 12-bit pieces.
   For example, suppose that you want
   [1].abc def x 2**k, where [1] is the hidden bit, abc is an 11 bit
   number, and def is a 12-bit number.  (This is going to be an IEEE single.)
   We can represent the mantissa as a'bc x 2**(-12) + def x 2**(-24),
   where a'bc is abc+512 (to restore the hidden bit).  For example,
   [1].5A3 2DF would be 0xDA3 x 2**(-12) + 0x2DF x 2**(-24)
3. Express the chunks using ldexp:
	ldexp((double) 0x5A3, -12) + ldexp((double) 0x2DF, -24)
   This should be exact.  If it isn't, you have worse things to worry about.
4. Scale the result to provide the right exponent:
	ldexp(ldexp(...,-12) + ldexp(...,-24) + ..., k)

If this doesn't work, you have worse problems to worry about than how to
get an exact constant.

There is one rather important thing to point out:  PLEASE don't include
"magic numbers" in your program without providing a way to calculate them.
(The "way" might be a separate program.)  If someone else tries to use your
code on a machine with a different floating-point system, and all they have
is your unexplained magic numbers, they will curse you and their answers
will be wrong.  I have tried porting programs with 7 decimal digit constants
to a machine with nearly 12 decimal digits of precision, and it was no fun
at all.

-- 
The Marxists have merely _interpreted_ Marxism in various ways;
the point, however, is to _change_ it.		-- R. Hochhuth.

scott@bbxsda.UUCP (Scott Amspoker) (02/06/91)

In article <1991Jan29.173341.11899@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
>In general, despite Doug's distaste for its complexity, IEEE floating
>point is an order of magnitude superior to the rest.  It was designed
>by people who understood numerical arithmetic.

The designers didn't necessarily understand business arithmetic.  It's a
pain in the rear trying to manage rounding errors and arbitrary *decimal*
precisions with a format that is fundamentally radix 2.  Other than that
it's a great format.

-- 
Scott Amspoker                       | 
Basis International, Albuquerque, NM |     This space available
(505) 345-5232                       | 
unmvax.cs.unm.edu!bbx!bbxsda!scott   |

dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) (02/07/91)

In <1700@bbxsda.UUCP> scott@bbxsda.UUCP (Scott Amspoker) writes:

>The designers didn't necessarily understand business arithmetic.

On the contrary, my opinion is that businesspeople don't understand
arithmetic.  Life for all of us would be so much simpler if all
business calculations assumed some reasonable fuzz value and stopped
worrying about lost or gained pennies.
--
Rahul Dhesi <dhesi%cirrusl@oliveb.ATC.olivetti.com>
UUCP:  oliveb!cirrusl!dhesi

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (02/08/91)

In article <1700@bbxsda.UUCP>, scott@bbxsda.UUCP (Scott Amspoker) writes:
> In article <1991Jan29.173341.11899@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
> >IEEE fp ... was designed by people who understood numerical arithmetic.

> The designers didn't necessarily understand business arithmetic.  It's a
> pain in the rear trying to manage rounding errors and arbitrary *decimal*
> precisions with a format that is fundamentally radix 2.  Other than that
> it's a great format.

IEEE 754 wasn't *INTENDED* for business arithmetic.  There are important
numerical reasons why radix 2 was chosen.
It is worth noting that the designers of 754 KNEW that radix 2 and
multiple-of-32-bit-word wasn't ideal for everyone.
That's why there is IEEE 854.  That covers arbitrary word lengths,
and it covers radix ***10*** as well as radix 2.
If you want to claim that the IEEE designers didn't understand business
arithmetic, attack the decimal part of IEEE 854.

It's also worth noting that IEEE 754 double precision gives you
exact +, -, *, div, and mod for integers of up to 15 decimal digits.

-- 
Professional programming is paranoid programming

bright@nazgul.UUCP (Walter Bright) (02/13/91)

In article <2929@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
/On the contrary, my opinion is that businesspeople don't understand
/arithmetic.  Life for all of us would be so much simpler if all
/business calculations assumed some reasonable fuzz value and stopped
/worrying about lost or gained pennies.

I disagree. Think about a bank calculating interest on all its 5.25% checking
accounts. A penny here, a penny there, after many thousands of transactions
this adds up to real money. There has been more than one bank fraud where
a programmer stole money by having partial pennies credited to his personal
account...

henry@zoo.toronto.edu (Henry Spencer) (02/20/91)

In article <265@nazgul.UUCP> bright@nazgul.UUCP (Walter Bright) writes:
>... There has been more than one bank fraud where
>a programmer stole money by having partial pennies credited to his personal
>account...

References?  This appears to be an urban legend.  Banks have known since
long before computers that they had to watch where the partial pennies went.
-- 
"Read the OSI protocol specifications?  | Henry Spencer @ U of Toronto Zoology
I can't even *lift* them!"              |  henry@zoo.toronto.edu  utzoo!henry

davem@elandes.UUCP (Dave Mathis) (02/20/91)

henry@zoo.toronto.edu (Henry Spencer) writes:

:In article <265@nazgul.UUCP> bright@nazgul.UUCP (Walter Bright) writes:
:>... There has been more than one bank fraud where
:>a programmer stole money by having partial pennies credited to his personal
:>account...

:References?  This appears to be an urban legend.  Banks have known since
:long before computers that they had to watch where the partial pennies went.
:-- 
:"Read the OSI protocol specifications?  | Henry Spencer @ U of Toronto Zoology
:I can't even *lift* them!"              |  henry@zoo.toronto.edu  utzoo!henry


	This is well documented in Superman 2 (or was it 3).

-- 
Dave Mathis		ELAN designs
UUCP:  	oliveb!elandes!davem		apple!spies!elandes!davem

johnm@cory.Berkeley.EDU (John D. Mitchell) (02/21/91)

In article <1991Feb19.234300.28830@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
>In article <265@nazgul.UUCP> bright@nazgul.UUCP (Walter Bright) writes:
>>... There has been more than one bank fraud where
>>a programmer stole money by having partial pennies credited to his personal
>>account...
>References?  This appears to be an urban legend.  Banks have known since
>long before computers that they had to watch where the partial pennies went.

Anybody trying to do it would be a very slick person indeed.  The banks
have teams of programmers that just hang around checking the other
teams (for bugs too :-) for just this sort of thing.


John "But hey it *might* be worth a try!" Mitchell
johnm@cory.Berkeley.EDU

dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) (02/22/91)

In <265@nazgul.UUCP> bright@nazgul.UUCP (Walter Bright) writes:

>Think about a bank calculating interest on all its 5.25% checking
>accounts. A penny here, a penny there, after many thousands of transactions
>this adds up to real money. There has been more than one bank fraud where
>a programmer stole money by having partial pennies credited to his personal
>account...

There are two issues here.  One is the type of rounding, i.e., whether
it's always up, always down, 5/4 rounding, or even/odd rounding.  (The
last is best if you want to avoid a net bias.)

The other issue is that of precision.  

You can use even/odd rounding without necessarily doing all
calculations in base 10.
--
Rahul Dhesi <dhesi%cirrusl@oliveb.ATC.olivetti.com>
UUCP:  oliveb!cirrusl!dhesi