Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 30 May 1997 12:30:45 -0800 (AKDT)
From:      Steve Howe <un_x@anchorage.net>
To:        freebsd-hackers <hackers@freebsd.org>
Subject:   bcc vs cc/gcc (float)
Message-ID:  <Pine.BSF.3.95q.970530121334.389A-100000@aak.anchorage.net>

next in thread | raw e-mail | index | archive | help

some old-timers to the list may remember this.  i found cc/gcc's float
operations inferior to Borland C's 16-bit DOS compiler while i was in the
process of porting some of my DOS code to BSD.  i apologize for the length
of the code that follows, but it's as small as i can make it to prove my
point.  i would like to know if this situation can/will be resolved ...

the code just does a simple "unsigned string to float" conversion
(which is where you can see the failure in accuracy occur) and then
a "float to unsigned string" conversion.  with Borland C, "pow" needs
to be "powl" and "fmod" needs to be "fmodl" - and the comment in "ftous"
needs to be uncommented (fix rounding errors).

i have taken a great deal of time creating this code to
show this point - and it should compile cleanly as is
under bcc/cc/gcc.  Borland C (4.51) can run this code
without any loss of accuracy.  please CC me, i'm not
subscribed.

thank you. (SNIP HERE)
-------------------------------------------------------------------------
unsigned char antoi (unsigned char c);
unsigned char itoan (unsigned char i);
unsigned long sblock (unsigned char *s, unsigned long bytes);
unsigned char *strrvs (unsigned char *s, unsigned short bytes);
unsigned char *ftous (unsigned char *s, long double val, unsigned char base);
long double   ustof (unsigned char *s,unsigned char base,unsigned short bytes);
/*****************************************************************************/

#include <math.h>
#include <stdio.h>
#include <ctype.h>

/*****************************************************************************/
void main           (unsigned char argc, unsigned char **argv) {

unsigned char s[99]="ffffffffffffffff"; long double ld;

     ld = ustof(s, 16, 0);

     printf("+ %Lf\n", ld);
     printf("+ %Lf\n", ld-9);

     ftous(s, ld, 16); printf("%s\n", s);

exit( 0 );}
/*****************************************************************************/
unsigned char antoi (unsigned char c) {

/* alnum to int */  if ( isdigit(c) ) c-=48;

else if ( isupper(c) ) c-=55; else if ( islower(c) ) c-=87;       return( c );}
/*****************************************************************************/
unsigned char itoan (unsigned char i) {

/* int to alnum */ if ( i<10 ) i+=48; else if ( i<36 ) i+=87;     return( i );}
/*****************************************************************************/
unsigned long sblock (unsigned char *s, unsigned long bytes)  {

/* size of block */                       return( bytes ? bytes : strlen(s) );}
/*****************************************************************************/
unsigned char *strrvs (unsigned char *s, unsigned short bytes) {

/* reverse string */

unsigned char c; unsigned short i=-1; bytes = sblock(s, bytes);

while ( ++i < --bytes ) { c=s[i]; s[i]=s[bytes]; s[bytes]=c; }    return( s );}
/*****************************************************************************/
unsigned char *ftous (unsigned char *s, long double val, unsigned char base) {

/* float to unsigned string */
                                                       /* if base>10 adjust  */
unsigned char *p=s;                                    /* to  alpha numeral  */

     if ( val < 0 ) val = -val; /* val+=0.49999999; <- needed for Borland C  */

     do { *p++ = itoan(fmod(val, base)); printf("- %s %Lf\n", s, val);
          val/=base;
     }    while ( val >= 1 );

     *p = 0;                                           return( strrvs(s, 0) );}
/*****************************************************************************/
long double ustof (unsigned char *s,unsigned char base,unsigned short bytes) {

/* unsigned string to float */                         /* if base>10 adjust  */

long double val=0; unsigned short p=0, len=sblock(s, bytes);

     while ( len-- ) { val += antoi(s[len]) * pow(base, p++);
                       printf("- %s %Lf\n", s, val);
     }                                                          return( val );}
/*****************************************************************************/

-------------------------------------------------------------------------
another minor note - in the "printf"s above, the code will crash
without the L in "%Lf" being specified for long double floats.
the code below will crash if the L in "%Lf" is specified for
long double floats. ???  i don't get it! 
-------------------------------------------------------------------------

/*****************************************************************************/

#include <math.h>
#include <stdio.h>
#include <ctype.h>

/*****************************************************************************/
void main           (unsigned char argc, unsigned char **argv) {

unsigned char i; long double ld=1;

     for ( i=0; i<17; ++i ) printf("%f\n", pow(16,i));

exit( 0 );}
/*****************************************************************************/

-------------------------------------------------------------------------
 Sleep: a sign a caffeine deprivation ... http://www.anchorage.net/~un_x
-------------------------------------------------------------------------




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.95q.970530121334.389A-100000>