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>