Page 1 of 2 12 Last
  • Jump to page:
    #1
  1. No Profile Picture
    .
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2002
    Posts
    296
    Rep Power
    12

    float numbers slightly out


    the code below gets numbers from freeform input and puts those numbers into an array of floats and prints that array. it all works fine apart from sometimes the decimal numbers are just slightly out, for example if this is input:

    5.5 45.8 -99.01

    the resulting floating point numbers that are printed out are:

    5.500000
    45.799999
    -99.010002

    so the first number's fine but then the next two numbers are slightly off for some reason. any idea why that is?

    Code:
    /* getfloat5-2.c: make floating point number array out of numbers found in freeform input.
    (not quite working but nearly - odd small decimal inaccuracies on the end
    sometimes for some reason.) */
    
    #include <stdio.h>
    #include "getch.c"
    #define SIZE 100
    
    main()
    {
    	int i, n, x, getfloat(float *);
    	float array[SIZE];
    	
    	for(n=0; n < SIZE && (i=getfloat(&array[n])) != EOF; n++)
    		if(i==0)	/* not a number - try to fill same array element again */
    			n--;
    	
    	printf("# of #'s: %d\n", n);
    	
    	for(x=0; x < n; x++)		/* print the results */
    		printf("%f\n",array[x]);
    }
    
    /* getfloat: get next float from input into *pn */
    int getfloat(float *pn)
    {
    	int c, sign;
    	float fraction;
    	
    	while(isspace(c=getch()))	/* skip white space */
    		;
    	if(!isdigit(c) && c != EOF && c != '+' && c != '-' && c != '.')
    		return 0;		/* it's not a number */
    	sign=(c=='-') ? -1 : 1;		/* record pos or neg */
    	if(c=='+' || c=='-') {
    		c=getch();
    		if(!isdigit(c) && c != EOF)
    			return 0;
    	}
    	for(*pn=0.0; isdigit(c); c=getch())	/* get integer part of number */
    		*pn=10 * *pn + (c-'0');
    	
    	fraction = 1.0;
    	if(c=='.') {		/* there's possibly a fraction part to come */
    		while(isdigit(c=getch())) {
    			*pn = 10.0 * *pn + (c - '0');
    			fraction *= 10.0;
    		}
    	}
    	*pn = sign * *pn / fraction; 
    	if(c != EOF)
    		ungetch(c);
    	return c;
    }
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Feb 2001
    Posts
    1,481
    Rep Power
    15
    I believe it has something to do with the fact you are storing a base 10 number in bytes which are in base 2(on or off, or 0 or 1), so the representation isn't exact.
  4. #3
  5. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,638
    Rep Power
    4247
    See this FAQ
    http://www.eskimo.com/~scs/C-faq/q14.1.html
    Hope this helps! :)
  6. #4
  7. No Profile Picture
    .
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2002
    Posts
    296
    Rep Power
    12
    right, i see. thanks v. much for the replies. i changed all the floats to doubles and got:

    5.500000
    45.800000
    -99.010000

    from:

    5.5 45.8 -99.01

    so that's good. thanks :)
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2002
    Location
    Blacksburg VA/Philly PA
    Posts
    38
    Rep Power
    12
    floats are more accurate than doubles, but if you are doing something that needs to be exact convert from floats to something like an unsigned int. then make an enumerated type to take care of the sign issues, then wrap it all together into a class. this should fix all the issues (of you have time to do it and everything)
  10. #6
  11. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,638
    Rep Power
    4247
    >> floats are more accurate than doubles
    It's the other way around.
  12. #7
  13. jasondoucette.com
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2003
    Location
    Canada
    Posts
    378
    Rep Power
    12
    Originally posted by balance
    right, i see. thanks v. much for the replies. i changed all the floats to doubles and got:

    5.500000
    45.800000
    -99.010000

    from:

    5.5 45.8 -99.01

    so that's good. thanks :)
    Remember that these numbers only appear to be correct since double stores more digits (binary digits) than you are actually outputting. As 7stud stated, some base 10 numbers cannot be stored exactly in base 2, no matter how many bits the floating point representation of it stores. Try and show more digits for the above, and you'll see that they, too, are not accurate. Perhaps they are now as accurate as you like them to be, though.
  14. #8
  15. No Profile Picture
    .
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2002
    Posts
    296
    Rep Power
    12
    right. i had a feeling that may be the case.

    i am quite surprised at this:- decimal numbers being innacurate on computers. very surprised even. never struck that that could be a problem or issue for them.
  16. #9
  17. jasondoucette.com
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2003
    Location
    Canada
    Posts
    378
    Rep Power
    12
    Remember that this is only the case for fractional values. Integers are stored perfectly in both INTEGER and FLOAT types (up to the storage limit, anyways).

    Also, if you think about it, it is not all that surprising that you cannot store some values accurately in base-2. You cannot store the 1/3 in base-10 accurately:
    0.33333333333333333...
    as you can only store so many 3's, even though 1/3 stores easily in base-3:
    0.1.

    This is the exact same problem as trying to store 1/10 in base-2:
    0.00011001100110011...
    even though it stores accurately in base-10:
    0.1

    Also consider that you cannot store a number such as PI accurately in any base.
  18. #10
  19. jasondoucette.com
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2003
    Location
    Canada
    Posts
    378
    Rep Power
    12
    Something else you may be interested in:

    Most calculators use Binary Coded Decimal (BCD) for storing numbers, which stores either 1 or 2 decimal digits per byte. So, the computations are done using decimal digits (this is not normally used for PCs since it is an awful waste of memory).

    This doesn't mean they are more accurate than base-2 storage of most CPUs, since it all depends on the amount of digits that are stored. My TI-85 stores 14 internal decimal digits and only displays 12, so the inaccuracy is not apparent except for when the accumulative error of multiple calculations makes at least 3 of the end digits of the 14-digit result inaccurate.

    Also, as I have explained above, certain numbers simply do not store accurately in certain bases. You can never get away with this. Base-10 is not, by any means, some perfect base. Some numbers store perfectly in some bases, and not in others - it all depends on the numbers and the base you are using.
  20. #11
  21. No Profile Picture
    .
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2002
    Posts
    296
    Rep Power
    12
    so maybe the wrong base has been used for pi? if you used the right base then you'd be able to fully and accurately describe it?
  22. #12
  23. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,638
    Rep Power
    4247
    Nope, pi can't be described accurately in any base. pi, e, sqrt(2) etc. all belong to a class of numbers called irrational numbers. However, a discussion about irrational numbers is beyond the scope of this forum, so google for more info, if you're interested :)
  24. #13
  25. jasondoucette.com
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2003
    Location
    Canada
    Posts
    378
    Rep Power
    12
    Originally posted by balance
    so maybe the wrong base has been used for pi? if you used the right base then you'd be able to fully and accurately describe it?
    No, please re-read the above two posts very carefully, because you do not understand exactly what I am saying. I said, "Also consider that you cannot store a number such as PI accurately in any base."

    Basically, computers are finite machines - they can store only a limited amount of information. Therefore, when you have more information to store than space to store it, you must lose some information. In terms of a number, we discard the most insignificant digits.

    Numbers such as pi and e cannot be described with a finite number of digits in any base, so no matter what base you choose, you have to stop storing digits when you run out of memory.

    Other numbers, such as 1/10, can be stored with a finite number of digits in base 10, like so: 0.1, and therefore it can be accurately stored in a computer system using base-10 (like most calculators that use BCD - binary coded decimal, which is base-10). But, when you try and store it in base-2, you get a repeated number, and therefore you must stop storing digits when you run out of space. Therefore, what you stored is not exactly 1/10. Hopefully, though, you only need 10 or 12 digits of accuracy, and since double can store 15 or 16, then this is good enough.

    I hope this clears things up for you.
    Last edited by Jason Doucette; March 4th, 2003 at 02:48 PM.
  26. #14
  27. No Profile Picture
    .
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2002
    Posts
    296
    Rep Power
    12
    irrational numbers - i like that.


    it was just a thought - forget it. :) thanks very much.
  28. #15
  29. jasondoucette.com
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2003
    Location
    Canada
    Posts
    378
    Rep Power
    12
    If you could get PI to be accurately described in a base, then we would have a fraction that could describe PI. Why? Because, let's say you have a number like so:

    0.abcdefgh

    where a through h are all digits of whatever base we are in (let's say base x), then this number can be described by this fraction:

    abcdefgh / x^8

    The 8 comes from the fact that there are 8 digits. Let me show you a simplier example of this, if you have this number:

    0.274 (in base-10, decimal)

    this can be described as:

    274 / 10^3 (which is equal to: 274 / 1000 which equals 0.274)

    PI cannot be described by a fraction (an integer divided by another integer), so it cannot be described accurately in any base, and is therefore an irrational number.
Page 1 of 2 12 Last
  • Jump to page:

IMN logo majestic logo threadwatch logo seochat tools logo