Sign in to follow this  
smc

float to string

Recommended Posts

If posting solutions to HW assignments is against the rules, then please remove. Here is my ugly recursive solution to an assignment.. This was done without using any knowledge of how floats are organized in memory. I am also sure there are much better solutions then this. The user need not specify any of the function parameters that have defaults. I have not proved it's correctness, nor do I think it is possible without understanding the IEEE standard. Please don't grip about using (bool)?val:val. I usually follow 'good practices' when using this, but today I am not. feel free to comment.
string ftos(float val, int prec, float multiplier = 10.0f, bool mul_flag = false, bool dec_flag = false) ;

/**
    Function to convert a floating point value into a string
 
 @param val         The value to convert
 @param prec        The precision to convert
 @param multiplier  The 'shifting' multiplier
 @param mul_flag    Flag to indicate we need to modify the multiplier to account for numerical
                    values before the decimal place.
 @param dec_flag    Flag to indicate we need to insert a decimal point into the string.
 
 */
string ftos(float val, int prec, float multiplier, bool mul_flag, bool dec_flag) {
    string s ;
    
    if(! prec)
        return string() ;
    
    if(val < 0) {
        s += "-" ;
        val = -val ;
    }
    if( val >= 1.0f && multiplier > 0 && !mul_flag) {
        mul_flag = true ;
        multiplier = 1.0f ;
        while( (int)(val * multiplier) >= 10) {
            multiplier *= 0.1f ;
        }
    }
    if(multiplier >= 10.0f && !dec_flag) {
        dec_flag = true ;
        s += (val < 1.0f? string("0") : string()) +  "." ;
    }
    char c = (char) ( ( (int)(val * ( multiplier >= 1.0f ? ( (int) multiplier): multiplier) ) % 10) + 48) ;
    return s + c + ftos( val, (multiplier >= 10.0f?--prec:prec), multiplier * 10.0f, mul_flag, dec_flag) ;
}

Share this post


Link to post
Share on other sites
The assignment was to write a recursive function to convert a signed float into a C++ string. This is my buggy implementation... found an issue with certain numbers. I think I should try a different approach.

The casting before the mod is what is causing problems. For example this will convert 10.23 to 10.22

Ohh well... good enough for this assignment. I should read the paper by R. Burger and R. Dybvig.

Share this post


Link to post
Share on other sites
Ok, forgetting the usual std::ostringstream, printf or ftoa routines..

Quote:
I have not proved it's correctness
It's a good practice to write correct algorithms.

Quote:
Please don't grip about using (bool)?val:val. I usually follow 'good practices' when using this, but today I am not.
I can't recall any really important rule about not using ternary operator.

Quote:
if(! prec)
return string() ;
What happens if prec is -1?

Quote:
if(val < 0) {
s += "-" ;
val = -val ;
}
-0.00000 is valid floating value, different from 0.00000.

Quote:
while( (int)(val * multiplier) >= 10) {
multiplier *= 0.1f ;
}
This is problematic. Repeatedly multiplying a float value by 0.1 will not yield consistent results. It could be something like 1.0, 0.1, 0.00999652, 0.00099421423. This is problematic because the above loop condition relies on accuracy.

The following, as represented in code: (multiplier * 0.1) * 10 may not equal multiplier due to rounding errors.


You'd probably need to support scientific notation as well, or 10e37 will result in 38 digit wide string.

Share this post


Link to post
Share on other sites

Quote:

Quote:
if(! prec)
return string() ;
What happens if prec is -1?


At a quick glance... dies of a stack overflow. Exactly as planned ;)

Quote:

Quote:
if(val < 0) {
s += "-" ;
val = -val ;
}
-0.00000 is valid floating value, different from 0.00000.

We do not have to cover all cases. This is a simple data structures and algorithms class. He does not expect us to know the 'inner workings' of floating point numbers. Ya I am using this as a copout.

Quote:

Quote:
while( (int)(val * multiplier) >= 10) {
multiplier *= 0.1f ;
}
This is problematic. Repeatedly multiplying a float value by 0.1 will not yield consistent results. It could be something like 1.0, 0.1, 0.00999652, 0.00099421423. This is problematic because the above loop condition relies on accuracy.


I have noticed that. This is why you see some casing to try and cast away these rounding errors. This is not working however.


In any case it was a fun exploratory assignment.

Share this post


Link to post
Share on other sites
Quote:

In any case it was a fun exploratory assignment.


It is interesting. So currently I'm trying to write a function that mirrors a default std::ostream for formatting (approximately), but iteratively. The first thing I thought when I read the initial post is... why the hell would anyone make such a function recursive!

If I don't get bored before I'm done, I might try convert the resulting function to a recursive one, just as a comparison.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this