Question

  • Platform: Linux 3.2.0 (Debian 7.0)
  • Compiler: GCC 4.7.2 (Debian 4.7.2-5)

I am trying to convert character strings into floats. I am aware that there are already functions that do this. I am only doing this for practice. My function works well with simple numbers like 123.123, 1234, -678.8. But when I try to convert the string .99999999 into a float I end up with 1. Which is obviously a problem. I do not know if this is because .99999999 cannot be expressed by a float or if I am doing something incorrectly. The question I am asking is how can I calculate the maximum fraction that a float can express. How do I, for lack of a better term, know when a float is about to overflow?

Here is what I have so far.

#include <stdio.h>
#include <stdlib.h>
#include <float.h>

int cstrtof(const char *cstr, float *f);
int cstrtof(const char *cstr, float *f)
{
unsigned short int i = 0;
unsigned short int bool_fraction = 0;
float tmp_f = 0;

if(cstr[0] == '\000') return -1;
else if(cstr[0] == '-') i = 1;

for(; cstr[i] != '\000'; i++)
{
    printf("tmp_f = %f\n", tmp_f);
    if(cstr[i] >= '0' && cstr[i] <= '9')
    {
        if(tmp_f > (FLT_MAX - (cstr[i] - '0')) / 10) return -2;
        else tmp_f = tmp_f * 10 + (cstr[i] - '0');
    }
    else if(cstr[i] == '.') bool_fraction = i+1;
    else return i+1;
}

printf("tmp_f = %f\nbool_fraction = %i\n", tmp_f, bool_fraction);

if(bool_fraction)
{
    for(bool_fraction--; bool_fraction < i-1;  bool_fraction++, tmp_f /= 10)
    {
        printf("tmp_f = %f\n", tmp_f);
    }
}

printf("tmp_f = %f\nbool_fraction = %i\n", tmp_f, bool_fraction);

if(cstr[0] == '-') *f = tmp_f*-1;
else *f = tmp_f;

return 0;
}

int main(int argc, char *argv[])
{
float f = 0;
int return_value = 0;

return_value = cstrtof(argv[1], &f);
if(return_value == 0)
{
    printf("f = %.11f\n", f);
}
else if(return_value == -1)
{
    printf("ERROR Empty String\n");
}
else if(return_value == -2)
{
    printf("ERROR Data Type Overflow\n");
}
else
{
    printf("ERROR Invalid character '%c'\n", argv[1][return_value-1]);
}

return 0;
}

Also cstrtof() is based on the following function.

int cstrtoslli(const char *cstr, signed long long int *slli)
{
unsigned short int i = 0;
signed long long int tmp_slli = 0;

if(cstr[0] == '\000') return -1;
else if(cstr[0] == '-') i = 1;
else if(cstr[0] == '0') return -2;

for(; cstr[i] != '\000'; i++)
{
    if(cstr[i] >= '0' && cstr[i] <= '9')
    {
              //LLONG_MAX is defined in limits.h
        if(tmp_slli > (LLONG_MAX - (cstr[i] - '0')) / 10) return -3;
        else tmp_slli = tmp_slli * 10 + (cstr[i] - '0');
    }
    else return i+1;
}

if(cstr[0] == '-') *slli = tmp_slli*-1;
else *slli = tmp_slli;

return 0;
}
Was it helpful?

Solution

The largest representable float value less than 1 is returned by nexttowardf(1, -INFINITY).

This will generally have a different fraction part than, for example, the largest representable float value less than 2, which is nexttowardf(2, -INFINITY). This is because numbers of different magnitudes generally have different numbers of bits available for the fraction part (because some of the bits are used for the integer part). Large numbers have zero bits for the fraction part.

When float is an IEEE-754 32-bit binary floating-point value, which is common in modern implementations, the largest float below 1 is 0.999999940395355224609375. When the routines that convert decimal numerals to float are good quality and the rounding mode is to-nearest (the common default), then the point where numbers switch from rounding to 0.999999940395355224609375 to rounding to 1 is halfway between those two values (and the exact midpoint will round to 1).

Properly converting decimal numerals to binary floating-point is complicated. It is a solved problem and there are academic papers about it, but you should generally rely on existing library code, if it is doing the job properly. Doing it correctly yourself will require a significant investment of time.

OTHER TIPS

The question I am asking is how can I calculate the maximum fraction that a float can express. How do I, for lack of a better term, know when a float is about to overflow?

You are looking for:

#include <math.h>
… nextafterf(1.0f, 0.0f) …

But you should familiarize yourself with C99's hexadecimal notation for floats, and then you can write the constant directly : 0x1.fffffep-1.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top