C Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me
Go Back   Dev Shed ForumsProgramming LanguagesC Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
Get inside! Sample the range of functionality easily built with JMSL Library for Time Series Data Analysis, Heat Maps, Portfolio Optimization, Monte Carlo Simulation, Stock Price Charting and more. Download Now!
  #1  
Old February 25th, 2003, 08:47 PM
balance balance is offline
.
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Dec 2002
Posts: 296 balance User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 6
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;
}

Reply With Quote
  #2  
Old February 25th, 2003, 08:57 PM
7stud 7stud is offline
Contributing User
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Feb 2001
Posts: 1,327 7stud User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 4 h 44 m 50 sec
Reputation Power: 9
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.

Reply With Quote
  #3  
Old February 25th, 2003, 09:18 PM
Scorpions4ever's Avatar
Scorpions4ever Scorpions4ever is offline
Banned ;)
Dev Shed God 5th Plane (7000 - 7499 posts)
 
Join Date: Nov 2001
Location: Glendale, Los Angeles County, California, USA
Posts: 7,442 Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level) 
Time spent in forums: 1 Month 2 h 5 m 45 sec
Reputation Power: 797
See this FAQ
http://www.eskimo.com/~scs/C-faq/q14.1.html
Hope this helps!

Reply With Quote
  #4  
Old February 25th, 2003, 09:56 PM
balance balance is offline
.
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Dec 2002
Posts: 296 balance User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 6
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

Reply With Quote
  #5  
Old February 26th, 2003, 02:21 PM
pschmerg pschmerg is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Nov 2002
Location: Blacksburg VA/Philly PA
Posts: 38 pschmerg User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 2 h 29 m
Reputation Power: 6
Send a message via AIM to pschmerg
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)

Reply With Quote
  #6  
Old February 26th, 2003, 04:37 PM
Scorpions4ever's Avatar
Scorpions4ever Scorpions4ever is offline
Banned ;)
Dev Shed God 5th Plane (7000 - 7499 posts)
 
Join Date: Nov 2001
Location: Glendale, Los Angeles County, California, USA
Posts: 7,442 Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level) 
Time spent in forums: 1 Month 2 h 5 m 45 sec
Reputation Power: 797
>> floats are more accurate than doubles
It's the other way around.

Reply With Quote
  #7  
Old February 28th, 2003, 01:28 PM
Jason Doucette's Avatar
Jason Doucette Jason Doucette is offline
jasondoucette.com
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Feb 2003
Location: Canada
Posts: 378 Jason Doucette User rank is Private First Class (20 - 50 Reputation Level)Jason Doucette User rank is Private First Class (20 - 50 Reputation Level) 
Time spent in forums: 7 h 23 m 8 sec
Reputation Power: 6
Quote:
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.

Reply With Quote
  #8  
Old March 3rd, 2003, 03:47 PM
balance balance is offline
.
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Dec 2002
Posts: 296 balance User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 6
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.

Reply With Quote
  #9  
Old March 3rd, 2003, 06:08 PM
Jason Doucette's Avatar
Jason Doucette Jason Doucette is offline
jasondoucette.com
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Feb 2003
Location: Canada
Posts: 378 Jason Doucette User rank is Private First Class (20 - 50 Reputation Level)Jason Doucette User rank is Private First Class (20 - 50 Reputation Level) 
Time spent in forums: 7 h 23 m 8 sec
Reputation Power: 6
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.

Reply With Quote
  #10  
Old March 4th, 2003, 08:44 AM
Jason Doucette's Avatar
Jason Doucette Jason Doucette is offline
jasondoucette.com
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Feb 2003
Location: Canada
Posts: 378 Jason Doucette User rank is Private First Class (20 - 50 Reputation Level)Jason Doucette User rank is Private First Class (20 - 50 Reputation Level) 
Time spent in forums: 7 h 23 m 8 sec
Reputation Power: 6
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.

Reply With Quote
  #11  
Old March 4th, 2003, 02:32 PM
balance balance is offline
.
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Dec 2002
Posts: 296 balance User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 6
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?

Reply With Quote
  #12  
Old March 4th, 2003, 02:43 PM
Scorpions4ever's Avatar
Scorpions4ever Scorpions4ever is offline
Banned ;)
Dev Shed God 5th Plane (7000 - 7499 posts)
 
Join Date: Nov 2001
Location: Glendale, Los Angeles County, California, USA
Posts: 7,442 Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level)Scorpions4ever User rank is Major General (70000 - 90000 Reputation Level) 
Time spent in forums: 1 Month 2 h 5 m 45 sec
Reputation Power: 797
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

Reply With Quote
  #13  
Old March 4th, 2003, 02:45 PM
Jason Doucette's Avatar
Jason Doucette Jason Doucette is offline
jasondoucette.com
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Feb 2003
Location: Canada
Posts: 378 Jason Doucette User rank is Private First Class (20 - 50 Reputation Level)Jason Doucette User rank is Private First Class (20 - 50 Reputation Level) 
Time spent in forums: 7 h 23 m 8 sec
Reputation Power: 6
Quote:
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.

Reply With Quote
  #14  
Old March 4th, 2003, 04:32 PM
balance balance is offline
.
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Dec 2002
Posts: 296 balance User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 6
irrational numbers - i like that.


it was just a thought - forget it. thanks very much.

Reply With Quote
  #15  
Old March 6th, 2003, 07:28 AM
Jason Doucette's Avatar
Jason Doucette Jason Doucette is offline
jasondoucette.com
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Feb 2003
Location: Canada
Posts: 378 Jason Doucette User rank is Private First Class (20 - 50 Reputation Level)Jason Doucette User rank is Private First Class (20 - 50 Reputation Level) 
Time spent in forums: 7 h 23 m 8 sec
Reputation Power: 6
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.