LinuxQuestions.org
Visit the LQ Articles and Editorials section
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 05-05-2009, 02:59 AM   #1
ivanatora
Member
 
Registered: Sep 2003
Location: Bulgaria
Distribution: Ubuntu 9.10, FreeBSD 7.2
Posts: 459

Rep: Reputation: 31
[C] scanf() read swrong floats; double goes fine


Hello,
This is a strange problem and I hope someone has an explanation to it.
When I use scanf() to read floating point numbers, sometimes the last digit is wrong.
Code:
#include <stdio.h>
int main(void)
{
    float f=0;
    scanf("%f", &f);
    printf("%f\n", f);
    return 0;
}
Here is example of working executable (note that only certain numbers are mistaken, not all):
Code:
Press ENTER or type command to continue
99.1
99.099998
Press ENTER or type command to continue
89.99
89.989998
Press ENTER or type command to continue
12.88
12.880000
Press ENTER or type command to continue
333.333
333.333008
Press ENTER or type command to continue
1313.1313
1313.131348
Press ENTER or type command to continue
99999.1
99999.101562
If I change float to double (and %f to %lf, respectively) every value is read correctly.
I know in GCC float is 4 bytes, but how much bytes are for the integer part and how much are for the fractional part of the number?
If there is at least 1 byte for the fractional part that gives the precision of about 0.004 that is more than enough for storing the number "99.1" correctly. Apparently even that small number is wrong.
 
Old 05-05-2009, 03:36 AM   #2
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 453Reputation: 453Reputation: 453Reputation: 453Reputation: 453
Quote:
Originally Posted by ivanatora View Post
Hello,
This is a strange problem and I hope someone has an explanation to it.
When I use scanf() to read floating point numbers, sometimes the last digit is wrong.
Code:
#include <stdio.h>
int main(void)
{
    float f=0;
    scanf("%f", &f);
    printf("%f\n", f);
    return 0;
}
Here is example of working executable (note that only certain numbers are mistaken, not all):
Code:
Press ENTER or type command to continue
99.1
99.099998
Press ENTER or type command to continue
89.99
89.989998
Press ENTER or type command to continue
12.88
12.880000
Press ENTER or type command to continue
333.333
333.333008
Press ENTER or type command to continue
1313.1313
1313.131348
Press ENTER or type command to continue
99999.1
99999.101562
If I change float to double (and %f to %lf, respectively) every value is read correctly.
I know in GCC float is 4 bytes, but how much bytes are for the integer part and how much are for the fractional part of the number?
If there is at least 1 byte for the fractional part that gives the precision of about 0.004 that is more than enough for storing the number "99.1" correctly. Apparently even that small number is wrong.
Don't even start dealing with floating point numbers (both 'float' and 'double') until you learn the basics of computer arithmetic.

Remember that a (non)periodic fraction in one radix is not necessarily the same in another. Modern computers by default do not count in decimal, they count in binary.

Start from here: http://en.wikipedia.org/wiki/Floating_point .

Last edited by Sergei Steshenko; 05-05-2009 at 05:49 AM.
 
Old 05-05-2009, 04:56 AM   #3
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
There is a simple question I ask people who think this is an error.
Can you accurately represent the value 1/3 in a base 10 system?
 
Old 05-05-2009, 05:45 AM   #4
ivanatora
Member
 
Registered: Sep 2003
Location: Bulgaria
Distribution: Ubuntu 9.10, FreeBSD 7.2
Posts: 459

Original Poster
Rep: Reputation: 31
Quote:
Originally Posted by dmail View Post
Can you accurately represent the value 1/3 in a base 10 system?
Actually, no. 0.33 (3 in period) is close but still not 1/3.
0.1 in decimal is 0.000110011 (0011 in period) in binary. So the precision is lost when converting it back to decimal? Maybe it is not exactly periodical and it is solved in more bits, is that why putting it in double works?
Other numbers that appeared wrong are also presented in more bits. This should be the reason of the precision drop when using floats - part of the significant bits are lost.
 
Old 05-05-2009, 06:09 AM   #5
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
Quote:
Originally Posted by ivanatora View Post
Actually, no. 0.33 (3 in period) is close but still not 1/3.
0.1 in decimal is 0.000110011 (0011 in period) in binary.
0.1 also can not be accurately represented in base 2, it would be
[0][01111011][110011001100110011001100]
Where the boxes represent different parts of the representation of the number in IEEE754. The first being the sign, next the exponent and last the mantissa. You can see the mantissa is a repeating sequence just like 0.33r has a repeating sequence.
Quote:
So the precision is lost when converting it back to decimal?
No the precision is lost due to the base system not being able to store the number accurately.
What Every Computer Scientist Should Know About Floating-Point Arithmetic

Last edited by dmail; 05-05-2009 at 06:13 AM.
 
Old 05-05-2009, 08:58 AM   #6
ivanatora
Member
 
Registered: Sep 2003
Location: Bulgaria
Distribution: Ubuntu 9.10, FreeBSD 7.2
Posts: 459

Original Poster
Rep: Reputation: 31
Thanks! Everything now is crystal clear.
 
  


Reply

Tags
compiler, double, float, gcc


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Read floats from file wsduvall Programming 2 03-10-2009 10:18 AM
cannot read from /dev/dsp but sound works fine otherwise polemon Linux - Hardware 0 01-14-2008 09:47 AM
scanf doesn't interrupt flow to read input ionuion Programming 3 04-25-2006 07:45 AM
reading from STD IN (scanf , gets and read wont work) nodger Programming 1 09-01-2004 04:47 PM
write/read double over a network champ Programming 5 09-14-2003 05:21 PM


All times are GMT -5. The time now is 08:35 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration