🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.gcc.help
Article #41960

Re: FP weirdness, i586, 2.7.0, linux

#41960
From: Steffen Winterfeldt
Date: Tue, 30 Jan 1996 00:00
77 lines
2400 bytes
Amish Dave (amish@data.uchicago.edu) wrote:
: On a P133 running Linux1.2.13 with gcc-2.7.0, I get strange behavior with
: the code below.  Sparc2-SunOS-gcc2.6.3 and Alpha-DecUNIX2.3c-gcc2.7.0
: behave correctly with the same code.
: 
: #include <stdio.h>
: main()
: {
: 	int a = 20, b = 50, c;
: 
: 	c = (int)(0.7 * (a + b));
: 	printf("c = %d\n", c);
: 
: 	c = (int)(0.7 * 70);
: 	printf("c = %d\n", c);
: }
: 
: When compiled without any options (gcc -o foo foo.c), on the Pentium, it
: prints out
: c = 48
: c = 49
: 
: What's going on?

This somewhat strange behavior results from the fact that the 80x86 FPU's
use an internal 80-bit representation of floating point numbers. A
double in C is only 64 bits.

There is no finite-length binary representation of 0.7. It is treated by
the compiler as double, that is 64 bits. When it is loaded into the FPU,
the missing bits are filled with zeros, resulting in a 80-bit number
that is actually about 0.7 - 2^(-64).

Then it is multiplied by 10, giving approximately 7 - 2^(-61).

So when this number is converted to int, it is ***rounded down***, giving 6.

When this number is stored into a double of 64 bits, it is
***rounded***, giving 7.000000... .
This number can then be converted to int giving 7.

gcc knows the type long double, that is 80 bits on 80x86's.
With this type there is of course no such trouble.

Here is a modified version of the above cited program, that
illustrates this effect:

#include <stdio.h>

void p(int i) { printf("0.7 * 10 = %i\n", i); }

void main() {
  int i, c = 10;
  double d;
  long double ld;

  i = (d = 0.7 * c);
  p(i);
  p(d);
  
  i = (ld = 0.7l * c);
  p(i);
  p(ld);
}

When run on a i486, it prints

0.7 * 10 = 6
0.7 * 10 = 7
0.7 * 10 = 7
0.7 * 10 = 7

When compiled with optimization the multiplication is done by
the compiler, of course.

Steffen
wfeldt@mickey.physik.uni-leipzig.de
Technical Details
Message-ID: <4el58f$6of@server2.rz.uni-leipzig.de>
Path: arc1-ca.pugleaf.net!unknown!not-for-mail
References: <DLtLuF.KEC@midway.uchicago.edu>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: 11318c,7168856f3962c151
X-Google-Attributes: gid11318c,public
From: wfeldt@physik.uni-leipzig.de (Steffen Winterfeldt)
Subject: Re: FP weirdness, i586, 2.7.0, linux
Date: 1996/01/30
Message-ID: <4el58f$6of@server2.rz.uni-leipzig.de>
X-Deja-AN: 137201440
distribution: world
references: <DLtLuF.KEC@midway.uchicago.edu>
organization: Uni Leipzig
newsgroups: gnu.gcc.help