1

I am trying to code a function that converts a double into a string (a sort of dtoa function). I don't want to use any of the standard library that will do all the job for me (itoa is ok, strlen too, because I can code them on my own). My main idea was to extract the integer part, doing something like this:

/* Let's suppose that str is ok, and d > 0 */
/* Let's also suppose that we don't need to round the result */
/* Let's finally suppose that precision is greater than 0 */

char *dtoa(double d, int precision, char *str)
{
    int     int_part;
    size_t  i, len;
    char    *temp;
    int     decimals;

    if (str == NULL)
        return (NULL);
    int_part = (int)d;
    temp = itoa(int_part);
    i = 0;
    len = strlen(temp);
    while (i < len)
    {
        str[i] = temp[i];
        i++;
    }
    d -= (double)int_part;
    str[i] = '.';
    i++;
    decimals = 0;
    while (decimals < precision)
    {
        d *= 10;
        int_part = (int)d;
        str[i] = int_part + '0';
        i++;
        decimals++;
        d -= (double)int_part;
    }
    return (str);
}

That function doesn't work so bad. I think I am a little bit stupid, because I could extract several decimal numbers instead of extracing them one by one. But, even when I tried this other method, I had a problem. Actually, when I do this, it works for a lot of double. But, for some of them, I am losing precision. For example, when I try with 1.42, I have 1.4199 as result.

My question is: is there an easy way to solve this problem, or do I need to change all the conversion method? A few years ago, I learned about how the floating point numbers where coded (using the IEE-754 representation) but I would like to avoid me to create a sort of IEE-754 converter.

Thanks for your help!

Edit: This is just an exercice, I'm not going to send a rocket to Mars with this function (the astronauts are grateful).

Edit2: It looks like 1.42 is not a "correct" double. But, in that case, why does this work fine?

printf("Number: %lf\n", 1.42);
CodeKiwi
  • 71
  • 1
  • 9
  • 1
    Not a duplicate, but related (as to why you get 1.4199 from 1.42): https://stackoverflow.com/questions/588004/is-floating-point-math-broken – TypeIA Dec 11 '18 at 15:09
  • 1
    `(int)d` isn't going to give you the full range of `double`. And `1.42` probably can't be exactly encoded by `double` anyway. – Weather Vane Dec 11 '18 at 15:10
  • 1
    Be aware of denormalized, infinite, and NaN floats (not to mention negatives). I understand this is likely a coding exercise, not bound-to-go-production code. Just sayin'. – DevSolar Dec 11 '18 at 15:15
  • 1
    “1.4199” is not incorrect for a `double` assigned from `1.42`. For the common 64-bit binary floating-point format, the representable value closest to 1.42 is 1.4199999999999999289457264239899814128875732421875. So, assigning `1.42` to `double` results in that value. – Eric Postpischil Dec 11 '18 at 15:23
  • 1
    To convert the fractional part of a floating-point number in an elementary way, you want to multiply only by the base of the floating-point format (or powers of it). Since a binary format is being used, you want to multiply by 2, not 10. When you multiply by 10, the result may have more significant bits than fit in the format. If so, then the result is rounded to the nearest representable value, causing an error. So it is necessary to multiply by 2 to extract the bits, then work with those bits in some extended-precision arithmetic to convert them to decimal. – Eric Postpischil Dec 11 '18 at 15:25
  • 1
    `printf("Number: %lf\n", 1.42);` prints “1.420000” because it rounds the `double` value, 1.4199999999999999289457264239899814128875732421875, to six digits after the decimal point. – Eric Postpischil Dec 11 '18 at 15:29
  • 2
    This is a deceptively hard problem. As you try to make your function better and better, you're going to discover more and more strange cases it can't handle, and you're going to learn more and more about floating point as you resolve those problems. – Steve Summit Dec 11 '18 at 15:32
  • 1
    For years it was an open research problem how to do this really well. Steele and White finally solved it adequately with their "Dragon" algorithm. – Steve Summit Dec 11 '18 at 15:35

0 Answers0