Thread: Anyone knows how I can convert a float/double to string?

  1. #1
    Registered User
    Join Date
    Oct 2021
    Posts
    138

    Anyone knows how I can convert a float/double to string?

    I want to do what the title says but without using any built-in functions. Anyone has any idea how I can do that? I made my research but I wasn't able to find a clear source that will post the source code.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Why do you need to do it without a library?

    sourceware.org Git - glibc.git/summary
    It'll be buried somewhere in there.

    But be warned, float to string conversion is a messy business at the best of times, with lots of corner cases.
    Production quality code that's been optimised for years on end (such as glibc) will be a PITA to read and comprehend.
    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.

  3. #3
    Registered User
    Join Date
    Oct 2021
    Posts
    138
    Quote Originally Posted by Salem View Post
    Why do you need to do it without a library?

    sourceware.org Git - glibc.git/summary
    It'll be buried somewhere in there.

    But be warned, float to string conversion is a messy business at the best of times, with lots of corner cases.
    Production quality code that's been optimised for years on end (such as glibc) will be a PITA to read and comprehend.
    I mean I was kinda afraid than in the end I'll have to read the ugly libc code but still I didn't lose anything to ask. I'm writing it myself because the language I want to use doesn't have a system library and someone has to write one. Tho I would like to use a system library as I don't like libc. ESPECIALLY GLIBC!!!! Thanks for your time man!

  4. #4
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    The algorithms are complicated. Keep in mind that floating point structure, in modern computers, follow the IEEE 754 model, where the value is stored as 3 unsigned integers following not ONE but TWO possible formulas:
    Anyone knows how I can convert a float/double to string?-fp-png
    And, for E=Emax, there are NANs... Notice the values are in base 2, not 10. S (1 bit), F (p-1 bits) and E (n bits, 8 for float, 11 for double and 15 for long double)... p is the precision, in bits (24 for float, 53 for double and 64 for long double). Ebias is 127 for float, 1023 for double and 16383 for long double.

    But if you want a generic approach, there are other representations of floating point in the wild you have to account for.

    In your scenario, if you don't want to use ANY external libraries, ALL floating point functions declared in math.h, all I/O functions in stdio.h, all library functions in string.h and stdlib.h, limits on limits.h and float.h are gone. You have to do it yourself.

    You can separate the integer part from the fractional and print it (but beware: since float has E, normalized, can have E=Emax-1, or E=254, the expoent is 127, (and the value is scaled by 2¹²⁷, as a 128 bits long integer)... Double, using 11 bits as expoent has a scaling factor of 1024 bits long, long double, 16384 bits long! None of these sizes can be used with int, long or long long objects! Here I am considering only those values scaled up to form big integer values.

    After that, you can multiply the fractional part by 10, get the integer part and subtract it, keeping in loop until get zero (or until you are satisfied)... Exemple:

    Code:
    0.725 * 10 = 7.25 (print 7 and keep 0.25
    0.25 * 10 = 2.5 (print 2 and keep 0.5)
    0.5 * 10 = 5.0 ( print 5 and keep 0.0 )
    0.0 (end)
    Last edited by flp1969; 12-04-2021 at 06:33 AM.

  5. #5
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    If you want some papers to study some refined algorithms for floating point printing. Here are some:

    Ryü - Fast Float-to-String Conversion
    Printing Floating-Point Numbers Accurately with Integers
    How to print floating-point numbers accurately

  6. #6
    Registered User
    Join Date
    Oct 2021
    Posts
    138
    Quote Originally Posted by flp1969 View Post
    If you want some papers to study some refined algorithms for floating point printing. Here are some:

    Ryü - Fast Float-to-String Conversion
    Printing Floating-Point Numbers Accurately with Integers
    How to print floating-point numbers accurately
    Thanks a lot!

  7. #7
    Registered User
    Join Date
    Oct 2021
    Posts
    138
    Quote Originally Posted by flp1969 View Post
    The algorithms are complicated. Keep in mind that floating point structure, in modern computers, follow the IEEE 754 model, where the value is stored as 3 unsigned integers following not ONE but TWO possible formulas:
    Anyone knows how I can convert a float/double to string?-fp-png
    And, for E=Emax, there are NANs... Notice the values are in base 2, not 10. S (1 bit), F (p-1 bits) and E (n bits, 8 for float, 11 for double and 15 for long double)... p is the precision, in bits (24 for float, 53 for double and 64 for long double). Ebias is 127 for float, 1023 for double and 16383 for long double.

    But if you want a generic approach, there are other representations of floating point in the wild you have to account for.

    In your scenario, if you don't want to use ANY external libraries, ALL floating point functions declared in math.h, all I/O functions in stdio.h, all library functions in string.h and stdlib.h, limits on limits.h and float.h are gone. You have to do it yourself.

    You can separate the integer part from the fractional and print it (but beware: since float has E, normalized, can have E=Emax-1, or E=254, the expoent is 127, (and the value is scaled by 2¹²⁷, as a 128 bits long integer)... Double, using 11 bits as expoent has a scaling factor of 1024 bits long, long double, 16384 bits long! None of these sizes can be used with int, long or long long objects! Here I am considering only those values scaled up to form big integer values.

    After that, you can multiply the fractional part by 10, get the integer part and subtract it, keeping in loop until get zero (or until you are satisfied)... Exemple:

    Code:
    0.725 * 10 = 7.25 (print 7 and keep 0.25
    0.25 * 10 = 2.5 (print 2 and keep 0.5)
    0.5 * 10 = 5.0 ( print 5 and keep 0.0 )
    0.0 (end)
    Lol, I understand now. It seems very complex. Thanks a lot!

  8. #8
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    An example without using functions from libc:
    Code:
    static inline void putstr( const void *ptr, unsigned int size )
    {
    // x86-64:
      // OBS: `syscall` can clobber RCX!
      __asm__ __volatile__ (
        "syscall"
        : : "a" (1), "D" (1), "S" (ptr), "d" (size)
        : "memory", "rcx"
      );
    
    // i386:
    //__asm__ __volatile__ (
    //  "int 0x80"
    //  : : "a" (4), "b" (1), "c" (ptr), "d" (size)
    //  : "memory"
    //);
    
    // arm (aarch32) -- change R0 to 64 for aarch64.
    //__asm__ __volatile__ (
    //  "svc $0"
    //  : : "r7" (4), "r0" (1), "r1" (ptr), "r2" (size)
    //  : "memory"
    //);
    }
    
    static inline void putchr( char c ) { putstr( &c, 1 ); }
    
    // Prints a decimal unsigned value (64 bits).
    __attribute__((noinline))
    void printu( unsigned long long int x )
    {
      char a[21];
      char *p, *endp;
    
      p = endp = a + sizeof a;
      do {
        *--p =  '0' + (x % 10);
      } while ( x /= 10 );
    
      putstr( p, endp - p );
    }
    
    static void printfrac( float x )
    {
      // This will fail if integer part > 2³²-1.
      x -= (unsigned long long int)x;
    
      do {
        int i;    // i < 10 always.
    
        x *= 10.0f;
        i = x;
        putchr( '0' + i );
        x -= i;
      } while ( x != 0.0f );
    }
    
    __attribute__((noinline))
    void printflt( float x )
    {
      static const char c = '.';
    
      // is value negative?
      if ( x < 0.0f )
      {
        static const char c = '-';
    
        putchr( '-' );
        x = -x;
      }
    
      // Gets the integer part and print.
      // This will fail if the integer part is greater than 2⁶⁴-1.
      printu( x );
    
      putchr( '.' );
    
      printfrac( x );
    }
    
    // Test!
    int main( void )
    {
      printflt( 3.14f );
      putchr( '\n' );
    }
    Last edited by flp1969; 12-04-2021 at 10:11 AM.

  9. #9
    Registered User
    Join Date
    Oct 2021
    Posts
    138
    Quote Originally Posted by flp1969 View Post
    An example without using functions from libc:
    Code:
    static inline void putstr( const void *ptr, unsigned int size )
    {
    // x86-64:
      // OBS: `syscall` can clobber RCX!
      __asm__ __volatile__ (
        "syscall"
        : : "a" (1), "D" (1), "S" (ptr), "d" (size)
        : "memory", "rcx"
      );
    
    // i386:
    //__asm__ __volatile__ (
    //  "int 0x80"
    //  : : "a" (4), "b" (1), "c" (ptr), "d" (size)
    //  : "memory"
    //);
    
    // arm (aarch32) -- change R0 to 64 for aarch64.
    //__asm__ __volatile__ (
    //  "svc $0"
    //  : : "r7" (4), "r0" (1), "r1" (ptr), "r2" (size)
    //  : "memory"
    //);
    }
    
    static inline void putchr( char c ) { putstr( &c, 1 ); }
    
    // Prints a decimal unsigned value (64 bits).
    __attribute__((noinline))
    void printu( unsigned long long int x )
    {
      char a[21];
      char *p, *endp;
    
      p = endp = a + sizeof a;
      do {
        *--p =  '0' + (x % 10);
      } while ( x /= 10 );
    
      putstr( p, endp - p );
    }
    
    static void printfrac( float x )
    {
      // This will fail if integer part > 2³²-1.
      x -= (unsigned long long int)x;
    
      do {
        int i;    // i < 10 always.
    
        x *= 10.0f;
        i = x;
        putchr( '0' + i );
        x -= i;
      } while ( x != 0.0f );
    }
    
    __attribute__((noinline))
    void printflt( float x )
    {
      static const char c = '.';
    
      // is value negative?
      if ( x < 0.0f )
      {
        static const char c = '-';
    
        putchr( '-' );
        x = -x;
      }
    
      // Gets the integer part and print.
      // This will fail if the integer part is greater than 2⁶⁴-1.
      printu( x );
    
      putchr( '.' );
    
      printfrac( x );
    }
    
    // Test!
    int main( void )
    {
      printflt( 3.14f );
      putchr( '\n' );
    }
    Well... Thanks a lot!!! This doesn't look so crazy as looking and understanding complex formulas or searching the 1.3M LoC Glibc's source code. Have a great day my friend!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Convert float to double
    By codewriter in forum C Programming
    Replies: 4
    Last Post: 08-10-2016, 12:20 AM
  2. Convert string to float
    By ching13 in forum C Programming
    Replies: 6
    Last Post: 05-07-2010, 02:58 PM
  3. Convert string to float?
    By tesla in forum C++ Programming
    Replies: 7
    Last Post: 09-22-2009, 05:39 AM
  4. help in convert String to float
    By kahwai1984 in forum C++ Programming
    Replies: 7
    Last Post: 03-19-2006, 09:21 PM
  5. convert float to string
    By vthokienj in forum C++ Programming
    Replies: 3
    Last Post: 12-14-2002, 11:33 AM

Tags for this Thread