really big doubles - why does atof() change it?

This is a discussion on really big doubles - why does atof() change it? within the C Programming forums, part of the General Programming Boards category; When putting the final touches on a regular expression test case, I decided to enter a whole bunch of numbers ...

  1. #1
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Katy, Texas
    Posts
    2,309

    really big doubles - why does atof() change it?

    When putting the final touches on a regular expression test case, I decided to enter a whole bunch of numbers to see what happened. Interestingly enough, it appeared to work, but my number changed.

    Here is my input number (the top one) and the output of atof(). My program follows. Why was my number changed?

    Code:
    985679876549857349857349857438957345987439058745985673498573498574398574395874
    985679876549857402577336704647254426385110368047371957249169051876711488028672.000000
    Source:
    Code:
    #include <stdio.h>
    #include <stdlib.h> 
    #include <string.h>
    #include <regex.h>
    
    void regex_error(regex_t * myregex, int rc ) { 
    	char mybuf[BUFSIZ] ; 
    	if (rc==0) return ; 
    	int re = regerror(rc, myregex, mybuf, BUFSIZ) ; 
    	printf("rc from regerror() = %d\n", re) ; 
    	perror(mybuf) ; 
    	exit(rc) ; 
    }
     
    int main (int argc, const char * argv[]) {
    	char data[80] ; 
    	int rc ; 
    	regex_t * myregex = calloc(1, sizeof(regex_t));
    	
    	// Compile the regular expression 
    	rc = regcomp( myregex, 
    		"^ *[-+]?([0-9]+(\\.[0-9]*)?|\\.[0-9]+)([eE][-+]?[0-9]+)? *$", 
    		REG_EXTENDED | REG_NOSUB ) ; 
    	regex_error(myregex, rc) ; 
    
    	printf("Enter a double value\n");
    	scanf("%s",data) ; 
    	
    	// Compare the entered value to the regex 
    	rc = regexec(myregex, data, 0 , 0 , 0 ) ; 
    	regex_error(myregex, rc) ; 
    
    	if (rc == 0) {
    		printf("double %s is valid.\n", data ) ; 
    		printf("converted value is %lf\n", atof(data) )  ; 
     
    	}
    	else { 
    		printf("double %s is not valid\n", data ); 
    		printf("converted value is %lf\n", atof(data) )  ; 
    	}
    	
    	// release all memory 
    	regfree(myregex) ; 
    	free(myregex) ;    
    	return 0;
    }
    Further testing shows that starting at 17 digits, the converted float value loses accuracy.
    Code:
    12345678901234567 - input value 
    12345678901234568.000000 - output value
    Entering 17 9's, I get this:
    Code:
    99999999999999999
    100000000000000000.000000
    Is this an architectural limit?

    Todd

  2. #2
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Because, floating points are only approximations.

    See http://en.wikipedia.org/wiki/Floatin...tual_computers, especially the 'Accuracy Problems' bit

  3. #3
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Katy, Texas
    Posts
    2,309
    It is (perhaps now was) my understanding that floating point approximations were only apparent for the fractional portion of a number.

    I just read a bit of that link - let's stir the pot:
    Quote Originally Posted by Wikipedia
    Any integer less than or equal to 2**24 can be exactly represented in the single precision format, and any integer less than or equal to 2**53 can be exactly represented in the double precision format.
    So, my understanding seems to be correct.

  4. #4
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Katy, Texas
    Posts
    2,309
    Hummm... perhaps a 17 digit number is > 2**53...

  5. #5
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Katy, Texas
    Posts
    2,309
    Yep, that's it.

    2**53 = 9007199254740992

    If I enter that, I get that back. If I enter 1 more,

    9007199254740993

    I get 9007199254740992.000000

    So, I hit the limit!

  6. #6
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,422
    In float.h, there is DBL_DIG
    This is the number of decimal digits of precision your floats can store (somewhere around 15 usually).

    This refers of course to most significant part of the number, and has no regard for where the decimal point is (it floats remember).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Todd Burch View Post
    It is (perhaps now was) my understanding that floating point approximations were only apparent for the fractional portion of a number.

    I just read a bit of that link - let's stir the pot:


    So, my understanding seems to be correct.
    As Salem hints, the "fraction part" is there in all numbers. The actual number is stored as (sign *)1.x * 2^n. So 0.5 is stored as 1*2^-1, for example. So "all" floating point numbers have a fraction.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Katy, Texas
    Posts
    2,309
    I guess it's a platform format thing.

    I'm used to working with floating point on IBM mainframes, in which the mantissa tells me how many bits are used for the whole portion of the number, and the rest of the bits (less sign and exponent) is the fraction.

    Also on IBM, there are normalized and unnormalized formats for floating point, and the unnormalized floats might not even have any fraction.

    Thanks.

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Sure, there are "normalized" and "denormalized" numbers in most floating point formats. I don't think your understanding of IBM's floating point format is correct tho', I found a document on Z-series floating point, and aside from having a non-IEEE compatible format called "Hexadecimal float", it doesn't differ noticeably from the IEEE standards.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #10
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Katy, Texas
    Posts
    2,309
    And that's what I'm used to working with - hexadecimal float - the "old stuff".

  11. #11
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Todd Burch View Post
    And that's what I'm used to working with - hexadecimal float - the "old stuff".
    Yes, but it still follows essentially the same principle - there is still a fraction somewhere in all floating point numbers - that's exactly what it's about, a "floating decimal point".

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. c++builder6 change form names problem
    By Leite33 in forum C++ Programming
    Replies: 2
    Last Post: 06-09-2008, 08:20 AM
  2. help with dividing doubles into integers
    By Amyaayaa in forum C++ Programming
    Replies: 4
    Last Post: 02-21-2008, 03:57 PM
  3. how to change static char* and not lose mem ?
    By jabka in forum C Programming
    Replies: 15
    Last Post: 09-07-2007, 05:33 PM
  4. Ask about how to change from int to unsigned char
    By ooosawaddee3 in forum C++ Programming
    Replies: 1
    Last Post: 07-08-2002, 01:07 AM
  5. Replies: 2
    Last Post: 09-04-2001, 02:12 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21