February 25th, 2003, 09:47 PM

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:
/* getfloat52.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;
}
February 25th, 2003, 09:57 PM

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.
February 25th, 2003, 10:18 PM

February 25th, 2003, 10:56 PM

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 :)
February 26th, 2003, 03:21 PM

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)
February 26th, 2003, 05:37 PM

>> floats are more accurate than doubles
It's the other way around.
February 28th, 2003, 02:28 PM

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.
March 3rd, 2003, 04:47 PM

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.
March 3rd, 2003, 07:08 PM

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 base2. You cannot store the 1/3 in base10 accurately:
0.33333333333333333...
as you can only store so many 3's, even though 1/3 stores easily in base3:
0.1.
This is the exact same problem as trying to store 1/10 in base2:
0.00011001100110011...
even though it stores accurately in base10:
0.1
Also consider that you cannot store a number such as PI accurately in any base.
March 4th, 2003, 09:44 AM

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 base2 storage of most CPUs, since it all depends on the amount of digits that are stored. My TI85 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 14digit 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. Base10 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.
March 4th, 2003, 03:32 PM

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?
March 4th, 2003, 03:43 PM

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 :)
March 4th, 2003, 03:45 PM

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 reread 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 base10 (like most calculators that use BCD  binary coded decimal, which is base10). But, when you try and store it in base2, 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 03:48 PM.
March 4th, 2003, 05:32 PM

irrational numbers  i like that.
it was just a thought  forget it. :) thanks very much.
March 6th, 2003, 08:28 AM

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 base10, 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.