From owner-freebsd-hackers Fri May 30 13:41:35 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.5/8.8.5) id NAA07290 for hackers-outgoing; Fri, 30 May 1997 13:41:35 -0700 (PDT) Received: from iceberg.anchorage.net. (root@iceberg.anchorage.net [207.14.72.150]) by hub.freebsd.org (8.8.5/8.8.5) with SMTP id NAA07282 for ; Fri, 30 May 1997 13:41:29 -0700 (PDT) Received: from aak.anchorage.net (ai-131 [207.14.72.131]) by iceberg.anchorage.net. (8.6.11/8.7.3) with SMTP id LAA03410 for ; Fri, 30 May 1997 11:38:02 -0800 Date: Fri, 30 May 1997 12:30:45 -0800 (AKDT) From: Steve Howe X-Sender: abc@aak.anchorage.net To: freebsd-hackers Subject: bcc vs cc/gcc (float) Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-hackers@freebsd.org X-Loop: FreeBSD.org Precedence: bulk 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 #include #include /*****************************************************************************/ 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 #include #include /*****************************************************************************/ 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 -------------------------------------------------------------------------