Use atof() or strtof()* instead:

printf("float value : %4.8f\n" ,atof(s)); 
printf("float value : %4.8f\n" ,strtof(s, NULL)); 

https://cplusplus.com/reference/cstdlib/atof/
https://cplusplus.com/reference/cstdlib/strtof/

  • atoll() is meant for integers.
  • atof()/strtof() is for floats.

The reason why you only get 4.00 with atoll() is because it stops parsing when it finds the first non-digit.

*Note that strtof() requires C99 or C++11.

Answer from Mysticial on Stack Overflow
Top answer
1 of 8
80

Use atof() or strtof()* instead:

printf("float value : %4.8f\n" ,atof(s)); 
printf("float value : %4.8f\n" ,strtof(s, NULL)); 

https://cplusplus.com/reference/cstdlib/atof/
https://cplusplus.com/reference/cstdlib/strtof/

  • atoll() is meant for integers.
  • atof()/strtof() is for floats.

The reason why you only get 4.00 with atoll() is because it stops parsing when it finds the first non-digit.

*Note that strtof() requires C99 or C++11.

2 of 8
38

Unfortunately, there is no way to do this easily. Every solution has its drawbacks.

  1. Use atof() or strtof() directly: this is what most people will tell you to do and it will work most of the time. However, if the program sets a locale or it uses a library that sets the locale (for instance, a graphics library that displays localised menus) and the user has their locale set to a language where the decimal separator is not . (such as fr_FR where the separator is ,) these functions will stop parsing at the . and you will stil get 4.0.

  2. Use atof() or strtof() but change the locale; it's a matter of calling setlocale(LC_ALL|~LC_NUMERIC, ""); before any call to atof() or the likes. The problem with setlocale is that it will be global to the process and you might interfer with the rest of the program. Note that you might query the current locale with setlocale() and restore it after you're done.

  3. Write your own float parsing routine. This might be quite quick if you do not need advanced features such as exponent parsing or hexadecimal floats.

Also, note that the value 4.08 cannot be represented exactly as a float; the actual value you will get is 4.0799999237060546875.

๐ŸŒ
TutorialsPoint
tutorialspoint.com โ€บ c_standard_library โ€บ c_function_atof.htm
C library - atof() function
The C stdlib library atof() function is used to convert a string into a floating-point number and represent the converted floating point number to its corresponding double value.
Discussions

Converting string to float in C? - Stack Overflow
Right, So in my C program i have a function that takes a float value from file, and here i am trying to do the reverse, taking the string and turning it into a float. float PsSc = atoi(stock01[ More on stackoverflow.com
๐ŸŒ stackoverflow.com
Converting a string to a float without using atof
What output do you get for a sample input? What do you expect to get? (Does it handle negative numbers? Exponents? Also, accurate string/floating point conversion is a non-trivial problem) More on reddit.com
๐ŸŒ r/C_Programming
7
2
March 5, 2018
parsing - C program to convert string to floating point - Code Review Stack Exchange
From K&R: Extend atof to handle scientific notation of the form 123.45e-6 where a floating-point number may be followed by e or E and an optionally signed exponent. I only added the part More on codereview.stackexchange.com
๐ŸŒ codereview.stackexchange.com
March 23, 2017
How to convert String to Float?
hey guys, i have a question. is it possible to convert from String to float data? here is my receiver program: // receiver Programming #include #include const int receive_pin = 12; String message; String myString; float nilaisatu; int nilaidua; int nilaitiga; int nilaiempat; float satuV0; #define ... More on forum.arduino.cc
๐ŸŒ forum.arduino.cc
0
0
July 6, 2019
Top answer
1 of 3
2

The strtod() function family is what you are looking for.

Not only will strtod() convert the input string to a double (with strtof() for float and strtold() for long double), it also tells you exactly where it stopped parsing the input string (through the second parameter).

Note that it is locale-dependent whether either strtod() or atof() expect a decimal point or a decimal comma...

#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <errno.h>

#include <stdio.h>

int main()
{
    // play with "." vs. "," to see why this might be your problem
    char * input = "1.45";

    // will take a pointer beyond the last character parsed
    char * end_ptr;

    // strto...() might give an error
    errno = 0;

    // convert
    float result = strtof( input, &end_ptr );

    if ( errno == ERANGE )
    {
        // handle out-of-range error - result will be HUGE_VALF
        puts( "out of range" );
    }

    if ( end_ptr != ( input + strlen( input ) ) )
    {
        // handle incomplete parse
        printf( "Unparsed: '%s'\n", end_ptr );
    }

    printf( "result: %.2f\n", result );
    return 0;
}
2 of 3
1

Why we shouldn't use atof

On success, atof() function returns the converted floating point number as a double value. If no valid conversion could be performed, the function returns zero (0.0). If the converted value would be out of the range of representable values by a double, it causes undefined behavior.

instead we should use strtod() present in <stdlib.h>

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
    char s[] = "1.45";
    printf("Float value : %4.2f\n",strtod(s,NULL));
    return 0;
}

it will correctly prints 1.45

See the illustration here http://ideone.com/poalgY

๐ŸŒ
Cprogramming
cboard.cprogramming.com โ€บ c-programming โ€บ 126650-convert-string-float.html
Convert string to float
July 23, 2025 - I generally use it for floating point input, and strtol for integer input. Have a look at this for an idea of how to implement your code. Of course the linked page deals with strtol, but after reading your documentation for both strtol and strtod, it is fairly trivial to use strtod in place of strtol for your needs. ... Do this using side-by-side development, i.e. check that your code gives the same answer as sscanf.
๐ŸŒ
Reddit
reddit.com โ€บ r/c_programming โ€บ converting a string to a float without using atof
r/C_Programming on Reddit: Converting a string to a float without using atof
March 5, 2018 -

I'm supposed to convert a string into a float without using any standard library function, and I can't figure out why this doesn't work.

float strToFloat(const char string[])
{
	int i;
	int j = 0;
	int ten = 1;
	float dec = 10;
	float result = 0;

	for (i = 0; string[i] != '\0'; ++i)
	{
		if (string[i] == '.')
		{
			for (; string[i] != '\0'; ++i)
			{
				dec = (dec * 10) + string[i] - '0';
				++j;
			}
		}
		else
			result = (result * 10) + string[i] - '0';
	}

	for (; i != 0; --i)
	{
		ten *= 10;
	}

	dec /= ten;
	printf("%d", dec);
	result += dec;
	
	return result;
}

Could someone help me?

Find elsewhere
๐ŸŒ
Cplusplus
cplusplus.com โ€บ reference โ€บ cstdlib โ€บ strtof
strtof - Convert string to float
Parses the C-string str interpreting its content as a floating point number (according to the current locale) and returns its value as a float. If endptr is not a null pointer, the function also sets the value of endptr to point to the first character after the number.
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ c language โ€บ gcvt-convert-float-value-string-c
gcvt() | Convert float value to string in C - GeeksforGeeks
April 25, 2017 - gcvt (float value, int ndigits, char * buf); float value : It is the float or double value. int ndigits : It is number of digits. char * buf : It is character pointer, in this variable string converted value will be copied.
Top answer
1 of 2
4

Thanks for including a test program - that's always valuable!

However, I'm going to change it, to parse a battery of test cases instead of reading from stdin:

#include <stdio.h>
int main(void)
{
    static const char *const strings[] = {
        /* these should parse fully */
        "12",
        "12.0",
        "08",                   /* not octal! */
        "+12.34",
        ".34",
        "\t \n2.",
        "1e0",
        "1e+0",
        "1e-0",
        "1.e4",
        ".1e-4",
        "-5e006",
        "-5e+16",
        "-.05",
        "-.0",
        "-1e6",
        /* these should parse only the initial part */
        "5c5",
        "10ee5",
        "0x06",                 /* not hex! */
        "--1" ,
        "-+1" ,
        "1e--4" ,
        "-1e.4",
        "1e 4",
        "1e-g",
        "", "foobar",           /* both 0 */
        " e5",                  /* also 0 */
        "-1e6",
        /* overflow/underflow */
        "1e500000",
        "1e-500000",
        "-1e500000",
        "-1e-500000",
    };

    static const int max = sizeof strings / sizeof strings[0];
    for (int i = 0;  i < max;  ++i)
        printf("%20s = > %.9g\n", strings[i], extended_atof(strings[i]));
}

(I changed the function name to extended_atof() so as to be safely distinct from the standard library atof().)

Your implementation passes all these tests. Now we can look at refactoring.

Remove duplication

The things that we parse in multiple places are:

  • optional sign + or -
  • digit sequences

So perhaps we can refactor each of those into a function? Instead of using an integer index into the supplied string, I prefer to just move the string pointer, and eliminate the need for i:

/* return true for positive, false for negative,
   and advance `*s` to next position */
static bool parse_sign(const char **s)
{
    switch (**s) {
    case '-': ++*s; return false;
    case '+': ++*s; return true;
    default: return true;
    }
}

Let's make use of that in the function:

double extended_atof(const char *s)
{
    /*skip white space*/
    while (isspace(*s))
        ++s;

    int sign = parse_sign(&s) ? 1 : -1; /*The sign of the number*/

    double value = 0.0;
    while (isdigit(*s))
        value = value * 10.0 + (*s++ - '0');

    if (*s == '.') {
        ++s;
    }

    double power = 1.0;
    while (isdigit(*s)) {
        value = value * 10.0 + (*s++ - '0');
        power *= 10.0;
    }

    if (tolower(*s) == 'e') {
        ++s;
    } else {
        return sign * value/power;
    }

    bool powersign = parse_sign(&s); /*The sign following the E*/

    int power2 = 0.0; /*The number following the E*/
    while (isdigit(*s))
        power2 = power2 * 10.0 + (*s++ - '0');

    if (powersign) {
        while (power2 != 0) {
            power /= 10;
            --power2;
        }
    } else {
        while (power2 != 0) {
            power *= 10;
            --power2;
        }
    }

    return sign * value/power;
}

It's slightly shorter, and it still passes all the tests.

Let's see if we can read digit strings in a function, and replace the three places we do that. We'll make it update a count of how many digits wore parsed, so we don't lose leading zeros in the fractional part:

double extended_atof(const char *s)
{
    /*skip white space*/
    while (isspace(*s))
        ++s;

    int sign = parse_sign(&s) ? 1 : -1; /*The sign of the number*/

    double value = parse_digits(&s, NULL);

    if (*s == '.') {
        ++s;
        int d;                  /* digits in fraction */
        double fraction = parse_digits(&s, &d);
        while (d--)
            fraction /= 10.0;
        value += fraction;
    }

    value *= sign;

    if (tolower(*s) == 'e') {
        ++s;
    } else {
        return value;
    }

    bool powersign = parse_sign(&s); /*The sign following the E*/

    int power2 = parse_digits(&s, NULL); /*The number following the E*/

    double power = 1.0;
    if (powersign) {
        while (power2 != 0) {
            power /= 10;
            --power2;
        }
    } else {
        while (power2 != 0) {
            power *= 10;
            --power2;
        }
    }

    return value/power;
}

Tests still pass; what's next?

if (tolower(*s) == 'e') {
    ++s;
} else {
    return value;
}

This can be reversed, and if we're returning, it doesn't matter what we do to s:

if (tolower(*s++) != 'e')
    return value;

Here's some near-duplicate blocks:

double power = 1.0;
if (powersign) {
    while (power2 != 0) {
        power /= 10;
        --power2;
    }
} else {
    while (power2 != 0) {
        power *= 10;
        --power2;
    }
}

Dividing by 10 is the same as multiplying by 0.1, so we can move the test into the loop:

double power = 1.0;
while (power2 != 0) {
    power *= powersign ? 0.1 : 10;
    --power2;
}

We could go further, and capture powersign ? 0.1 : 10 into a variable. We can also eliminate the power variable from here, and multiply value directly:

const double exponentsign = parse_sign(&s) ? 10. : .1;
int exponent = parse_digits(&s, NULL);

while (exponent--)
    value *= exponentsign;

Final version

Here's what I finished up with:

#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>

/* return true for positive, false for negative,
   and advance `*s` to next position */
static bool parse_sign(const char **const s)
{
    switch (**s) {
    case '-': ++*s; return false;
    case '+': ++*s; return true;
    default: return true;
    }
}

/* return decimal value of digits,
   advancing `*s` to the next character,
   and storing the number of digits read into *count */
static double parse_digits(const char **const s, int *const count)
{
    double value = 0.0;
    int c = 0;
    while (isdigit(**s)) {
        value = value * 10.0 + (*(*s)++ - '0');
        ++c;
    }
    if (count)
        *count = c;
    return value;
}

double extended_atof(const char *s)
{
    /*skip white space*/
    while (isspace(*s))
        ++s;

    const bool valuesign = parse_sign(&s); /* sign of the number */
    double value = parse_digits(&s, NULL);

    if (*s == '.') {
        int d;                  /* number of digits in fraction */
        ++s;
        double fraction = parse_digits(&s, &d);
        while (d--)
            fraction /= 10.0;
        value += fraction;
    }

    if (!valuesign)
        value = -value;

    if (tolower(*s++) != 'e')
        return value;

    /* else, we have an exponent; parse its sign and value */
    const double exponentsign = parse_sign(&s) ? 10. : .1;
    int exponent = parse_digits(&s, NULL);
    while (exponent--)
        value *= exponentsign;

    return value;
}


/* Test program */
#include <stdio.h>
int main(void)
{
    static const char *const strings[] = {
        /* these should parse fully */
        "12",
        "12.0",
        "08",                   /* not octal! */
        "+12.34",
        ".34",
        "\t \n2.",
        "1e0",
        "1e+0",
        "1e-0",
        "1.e4",
        ".1e-4",
        "-5e006",
        "-5e+16",
        "-.05",
        "-.0",
        "-1e6",
        /* these should parse only the initial part */
        "5c5",
        "10ee5",
        "0x06",                 /* not hex! */
        "--1" ,
        "-+1" ,
        "1e--4" ,
        "-1e.4",
        "1e 4",
        "1e-g",
        "", "foobar",           /* both 0 */
        " e5",                  /* also 0 */
        "-1e6",
        /* overflow/underflow */
        "1e500000",
        "1e-500000",
        "-1e500000",
        "-1e-500000",
    };

    static const int max = sizeof strings / sizeof strings[0];
    for (int i = 0;  i < max;  ++i)
        printf("%20s = > %.9g\n", strings[i], extended_atof(strings[i]));
}

There's still an opportunity for a small improvement: an extremely long fractional part could overflow double (this problem existed in your original). Instead of returning a large value from parse_int(), you could consider always returning a fractional value in the range [0...1), and use the number of digits to scale up the integer parts. Then we'd just end up with lost precision at the lower end. That would look like:

static double parse_digits(const char **const s, int *const count)
{
    double value = 0.0;
    double increment = 0.1;
    int c = 0;
    while (isdigit(**s)) {
        value += increment * (*(*s)++ - '0');
        increment /= 10;
        ++c;
    }
    if (count)
        *count = c;
    return value;
}

The corresponding uses would be:

double extended_atof(const char *s)
{
    /*skip white space*/
    while (isspace(*s))
        ++s;

    int d;                  /* number of digits */
    const bool valuesign = parse_sign(&s); /* sign of the number */
    double value = parse_digits(&s, &d);
    while (d--)
        value *= 10;

    if (*s == '.') {
        ++s;
        double fraction = parse_digits(&s, NULL);
        value += fraction;
    }

    if (!valuesign)
        value = -value;

    if (tolower(*s++) != 'e')
        return value;

    /* else, we have an exponent; parse its sign and value */
    const double exponentsign = parse_sign(&s) ? 10. : .1;
    double exponent_f = parse_digits(&s, &d);
    while (d--)
        exponent_f *= 10;

    unsigned long exponent = exponent_f;
    while (exponent-->0)
        value *= exponentsign;

    return value;
}
2 of 2
1

I think that the worst case of duplication that you need to remove from your code is writing another set of lines for reading the floating number after e (/E).

Even I am just a beginner and doing K&R right now. Here's what I thought when doing the exercise:

For extending the program to handle scientific notations the first thing that I require is to read another floating point number after the character e/E. The code for doing this is already present in the function. Which makes it obvious that we are to reuse that code somehow. I thought that no extra lines of code should should be written for implementing this functionality.

I found that using recursion along with math.h library shortened and simplified the code (particularly the part used for reading the number following e/E) quite considerably.

Here's the code that I wrote:

#include<stdio.h>
#include<ctype.h>
#include<math.h>
#include<string.h>

double atof(char *);

int main(void)
{
    char num[20];
    scanf("%19s", num);
    double number=atof(num);
    printf("\n%lf", number);
    return 0;
}

double atof(char *num)
{
    double val=0.0;
    int place=1;
    double expo=1.0;
    int i=0;
    int sign=1;
    for(; isspace(num[i]); i++);    //skip spaces
    sign=(num[i]=='-')?-1:1;    //determine sign
    if(num[i]=='-'||num[i]=='+')
        ++i;

    while(isdigit(num[i])){ //digits before decimal
        val=(val*10)+(num[i]-'0');
        ++i;
    }

    if(num[i]=='.')  //skip decimal point if present
        ++i;

    while(isdigit(num[i])){ //digits after decimal
        val=val*10+(num[i]-'0');
        place*=10;
        i++;
    }

    if(num[i]=='e' || num[i]=='E'){  //the extended part for scientific notations
        ++i;
        expo=pow(10,atof(num+i));
    }
    return (sign*val*expo)/(place);
}
๐ŸŒ
W3Schools Blog
w3schools.blog โ€บ home โ€บ convert string to float c
convert string to float c - W3schools.blog
October 31, 2011 - [ad_1] convert string to float c char myString = "6.88"; float x = atof(myString); //x is now 6.88 int to float c float percentage; percentage = (float)number/total * 100; [ad_2] Please follow and like us:
๐ŸŒ
O'Reilly
oreilly.com โ€บ library โ€บ view โ€บ c-in-a โ€บ 0596006977 โ€บ re14.html
atof - C in a Nutshell [Book]
December 16, 2005 - The atof() function converts a string of characters representing a numeral into a floating-point number of type double. The string must be in a customary floating-point numeral format, including scientific notation (e.g., 0.0314 or 3.14e-2). ...
Authors ย  Peter PrinzTony Crawford
Published ย  2005
Pages ย  618
๐ŸŒ
Mbed
os.mbed.com โ€บ questions โ€บ 7171 โ€บ How-to-convert-String-to-Float-value
How to convert String to Float value - Question | Mbed
June 4, 2017 - For this conversion you should probably use double instead of float (however give it a try with floats you should quickly see the issue). double iPart = 0.0, dPart = 0.0, f = 0.0, mult = 0.1; const char *buff = "12345.432"; sscanf(buff,"%f",&f); printf("%f\n",f); f= 0.0; char *p = (char*) buff; while(*p != '.') { iPart = iPart*10 + ((*(p++)-'0')); } p++; while(*p!= '\0') { dPart += ((*(p++)-'0'))*mult; mult *= 0.1; } f = iPart + dPart; printf("%f\n",f); The scanf is big function able to handle lost of conversion etc etc..
๐ŸŒ
Rastport
rastport.com โ€บ techblog โ€บ string-to-float
RastPort: Tech Blog โ€“ String to Floating Point Number Conversion
December 22, 2017 - The article describes string to ... hand it works in rounding towards zero mode, so it's not an exact counterpart of strtod() function....
๐ŸŒ
Cplusplus
cplusplus.com โ€บ reference โ€บ string โ€บ stof
std::stof - string
May 30, 2014 - String object with the representation of a floating-point number. ... Pointer to an object of type size_t, whose value is set by the function to position of the next character in str after the numerical value. This parameter can also be a null pointer, in which case it is not used. On success, the function returns the converted floating-point number as a value of type float.
๐ŸŒ
Arduino Forum
forum.arduino.cc โ€บ projects โ€บ programming
How to convert String to Float? - Programming - Arduino Forum
July 6, 2019 - hey guys, i have a question. is it possible to convert from String to float data? here is my receiver program: // receiver Programming #include #include const int receive_pin = 12; String message; String myString; float nilaisatu; int nilaidua; int nilaitiga; int nilaiempat; float satuV0; #define ena 5 #define enb 6 #define in1 8 #define in2 9 #define in3 10 #define in4 11 L298N motor(ena,in1,in2); L298N motor2(enb, in3,in4); void setup() { delay(5...
๐ŸŒ
Microsoft Learn
learn.microsoft.com โ€บ en-us โ€บ cpp โ€บ c-runtime-library โ€บ reference โ€บ strtof-strtof-l-wcstof-wcstof-l
strtof, _strtof_l, wcstof, _wcstof_l | Microsoft Learn
March 23, 2017 - The sign of HUGE_VALF matches the sign of the value that can't be represented. strtof returns 0 if no conversion can be performed or an underflow occurs. wcstof returns values analogously to strtof. For both functions, errno is set to ERANGE if overflow or underflow occurs and the invalid parameter handler is invoked, as described in Parameter validation. For more information about return codes, see errno, _doserrno, _sys_errlist, and _sys_nerr. Each function converts the input string strSource to a float.