[comp.lang.c] Why do most C compilers poxily round towards zero ?

peterf@arp.anu.oz.au (Peter Fletcher) (10/10/90)

One of the most frustrating things about using floating point in C is the
poxy way rounds floating point numbers towards zero instead of -infinity.

This creates a big inconsistency around 0.0 and makes any sort of consistent
rounding a bigger hassle than you'd like:

To round a number, instead of

	int a;
	float b;
	...
	a = (int)(b+0.5);

you need to do

	a = (b>0.0) ? (int)(b+0.5) : (int)(b-0.5);

Worse, to floor a number, instead of

        a = (int)b;

you need to do either

	a = floor(b); or
	a = (b>0.0) ? (int)b : -(int)(-b);

Also, you have silly situations where

	(int)(b-10.0)+10 doesn't always equal (int)b

I don't think this policy is in any of the C specifications, but it occurs
in all the C compilers I've used (sun, apollo, pyramid).  Does anyone know
why ?

I think with Suns and Apollos you can tell the floating point hardware
to use a different rounding mode, but it seems that both methods are
completely different and probably not compatible with anybody else.
Is there a reasonably standard Unix way to do this ?

-peter fletcher 
-------------------------------------------------------------------------------
Internet : peterf@csis.dit.csiro.au
Phone    : +61-6-2750914
Fax      : +61-6-2571052
Physical : CSIRO Division of Information Technology,
           ANU, Acton, Canberra ACT AUSTRALIA
-------------------------------------------------------------------------------

shirono@ssd.csd.harris.com (Roberto Shironoshita) (10/10/90)

In article <1990Oct9.230928.27552@arp.anu.oz.au> peterf@arp.anu.oz.au (Peter Fletcher) writes:

> [ Gripe about float-to-int conversion ]
> I don't think this policy is in any of the C specifications, but it occurs
> in all the C compilers I've used (sun, apollo, pyramid).  Does anyone know
> why ?

It is important to understand that, in type demotion, C doesn't round
either way; it simply eliminates that which it cannot use.

K&R chapter 2, pp. 41 & 42:

  Conversions take place accross assignments; the value of the right side
  is converted to the type of the left, which is the type of the result.
  [...]
  If x is float and i is int, then
	x = i
  and
	i = x
  both cause conversions; float to int causes truncation of any fractional
  part.

BTW, I doubt this is going to go away.  In the December 1988 Draft of ANS
X3.159-1989 (ANSI C), section 3.2.1.3 "Floating and integral":

  When a value of floating type is converted to integral type, the
  fractional part is discarded.  If the value of the integral part cannot
  be represented by the integral type, the behavior is undefined.

> I think with Suns and Apollos you can tell the floating point hardware
> to use a different rounding mode, but it seems that both methods are
> completely different and probably not compatible with anybody else.
> Is there a reasonably standard Unix way to do this ?

If you want rounding, you will have to do it yourself.  C won't do it for
you.
--

     Roberto Shironoshita      ||   Internet: shirono@ssd.csd.harris.com
      Harris Corporation       ||
   Computer Systems Division   ||   UUCP:     ...!uunet!hcx1!shirono
                               ||
DISCLAIMER: The opinions expressed here are my own; they in no way reflect the
            opinion or policies of Harris Corporation.

henry@zoo.toronto.edu (Henry Spencer) (10/10/90)

In article <1990Oct9.230928.27552@arp.anu.oz.au> peterf@arp.anu.oz.au (Peter Fletcher) writes:
>One of the most frustrating things about using floating point in C is the
>poxy way rounds floating point numbers towards zero instead of -infinity.

Unfortunately, this is generally a property of the hardware, introduced
mostly for consistency with the FORTRAN spec, which specifically calls
for rounding toward zero.

>I don't think this policy is in any of the C specifications...

Alas, not so.  ANSI C specifies that conversion from floating-point to
integer format discards the fraction.

However, all is not hopelessly lost, because ANSI C also does provide
the floor() function, and puts enough constraints on library functions
that smart compilers can inline them for speed.

>I think with Suns and Apollos you can tell the floating point hardware
>to use a different rounding mode, but it seems that both methods are
>completely different and probably not compatible with anybody else.
>Is there a reasonably standard Unix way to do this ?

Unfortunately, no.  We need better support of IEEE floating-point facilities
in our programming languages (and, to some extent, our operating systems).
-- 
Imagine life with OS/360 the standard  | Henry Spencer at U of Toronto Zoology
operating system.  Now think about X.  |  henry@zoo.toronto.edu   utzoo!henry

peter@ficc.ferranti.com (Peter da Silva) (10/11/90)

In article <1990Oct9.230928.27552@arp.anu.oz.au> peterf@arp.anu.oz.au (Peter Fletcher) writes:
> One of the most frustrating things about using floating point in C is the
> poxy way rounds floating point numbers towards zero instead of -infinity.

The same problem exists with the modulus operator. Mathematically, the
modulus operator !A mod B! should produce a result in the range !0..B-1!.
In fact, it produces a result in the range !1-B..B-1!. This means to do
anything useful with it, when you don't know the sign of !A!, you need
to calculate !(A % B + B) % B! or !(A<0)?((-A)%B):(A%B)!.
-- 
Peter da Silva.   `-_-'
+1 713 274 5180.   'U`
peter@ferranti.com

jrv@sdimax2.mitre.org (VanZandt) (10/11/90)

In article <XTB6WKB@xds13.ferranti.com> peter@ficc.ferranti.com (Peter da Silva) writes:
>In article <1990Oct9.230928.27552@arp.anu.oz.au> peterf@arp.anu.oz.au (Peter Fletcher) writes:
>> One of the most frustrating things about using floating point in C is the
>> poxy way rounds floating point numbers towards zero instead of -infinity.
>
>The same problem exists with the modulus operator. Mathematically, the
>modulus operator !A mod B! should produce a result in the range !0..B-1!.
>In fact, it produces a result in the range !1-B..B-1!. 

Amen!  I vote for a library function to calculate the modulus the right
way, which compiler writers could then expand inline.  (Incidently, although
I have several times needed to use a negative first argument, I've
never needed a negative second argument.  Are there really applications
for A mod B where B<0?)

                                   - Jim Van Zandt

henry@zoo.toronto.edu (Henry Spencer) (10/11/90)

In article <SHIRONO.90Oct10114447@gcx1.ssd.csd.harris.com> shirono@ssd.csd.harris.com writes:
>It is important to understand that, in type demotion, C doesn't round
>either way; it simply eliminates that which it cannot use.

This is a form of rounding (although not a very useful one).  There are
half a dozen different rounding algorithms; "rounding" is not a precise
term referring to one and only one.
-- 
Imagine life with OS/360 the standard  | Henry Spencer at U of Toronto Zoology
operating system.  Now think about X.  |  henry@zoo.toronto.edu   utzoo!henry

dik@cwi.nl (Dik T. Winter) (10/12/90)

In article <1990Oct11.161737.10969@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
 > In article <SHIRONO.90Oct10114447@gcx1.ssd.csd.harris.com> shirono@ssd.csd.harris.com writes:
 > >It is important to understand that, in type demotion, C doesn't round
 > >either way; it simply eliminates that which it cannot use.
 > 
 > This is a form of rounding (although not a very useful one).  There are
 > half a dozen different rounding algorithms; "rounding" is not a precise
 > term referring to one and only one.
I tend to disagree, but this may be quibbling.  Rounding is a very precise
term.  You may round a floating point value to an integer, or a real number
to a floating point value.  That is what rounding does: giving less
precision.  But as Henry Spencer notes: there are several rounding
algorithms (cf. IEEE).
--
dik t. winter, cwi, amsterdam, nederland
dik@cwi.nl

henry@zoo.toronto.edu (Henry Spencer) (10/12/90)

In article <XTB6WKB@xds13.ferranti.com> peter@ficc.ferranti.com (Peter da Silva) writes:
>> One of the most frustrating things about using floating point in C is the
>> poxy way rounds floating point numbers towards zero instead of -infinity.
>
>The same problem exists with the modulus operator. Mathematically, the
>modulus operator ...

C has no modulus operator.  `%' is documented in both K&R and ANSI C as
the remainder operator.
-- 
"...the i860 is a wonderful source     | Henry Spencer at U of Toronto Zoology
of thesis topics."    --Preston Briggs |  henry@zoo.toronto.edu   utzoo!henry