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>
