|
|
|||||||||
|
|||||||||
| |||||||||
|
|
|
| |||||||||
![]() |
|
|
«
Previous Thread
|
Next Thread
»
|
Thread Tools | Search this Thread | Rate Thread | Display Modes |
|
|
|
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
|
|||
|
|||
|
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
|
|||
|
|||
|
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.
|
|
#3
|
||||
|
||||
|
|
|
#4
|
|||
|
|||
|
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 ![]() |
|
#5
|
|||
|
|||
|
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)
|
|
#6
|
||||
|
||||
|
>> floats are more accurate than doubles
It's the other way around. |
|
#7
|
||||
|
||||
|
Quote:
__________________
Jason Doucette / Xona.com™ - Programming Windows Errata Addendum "Discussion is an exchange of knowledge; argument is an exchange of ignorance." |
|
#8
|
|||
|
|||
|
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. |
|
#9
|
||||
|
||||
|
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. |
|
#10
|
||||
|
||||
|
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. |
|
#11
|
|||
|
|||
|
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?
|
|
#12
|
||||
|
||||
|
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
![]() |
|
#13
|
||||
|
||||
|
Quote:
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. |
|
#14
|
|||
|
|||
|
irrational numbers - i like that.
it was just a thought - forget it. thanks very much. |
|
#15
|
||||
|
||||
|
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. |