Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I convert a string to double using only math.h

I'm trying to convert a string to a double, but since I'm working on a Windows native application (as in linking only to ntdll.dll), I don't have most of the standard library available. I can use basic FP support in math.h, but that's basically it.

How do I convert a string to the double closest to the rational number expressed in that string?

like image 925
avakar Avatar asked Feb 17 '11 11:02

avakar


3 Answers

If you really want to get the nearest, the problem is quite hard and you need arbitrary precision arithmetic to achieve that result. See ftp://ftp.ccs.neu.edu/pub/people/will/howtoread.ps for instance.

like image 199
AProgrammer Avatar answered Sep 18 '22 23:09

AProgrammer


Have you seen Open NT Native Template Library, particularly the STLx part? Basically, you get something close to normal C++ runtime in Native or Kernel code.

like image 22
atzz Avatar answered Sep 18 '22 23:09

atzz


Assuming the JSON grammar (link currently down, Google cached version here) is acceptable to you, the following comes more or less direct from internally developed code for JSON parsing, being a literal implementation of its syntax diagram:

/*

    defined functions for handling the input:

        nextChar() - peeks at the next character of input

        getAndRemoveCharacter() - returns the next character of input and
        dequeues it

    This code also assumes you have BOOL, YES and NO defined; I've left this in
    for clarity
*/

double getNumber()
{
    // determine whether the number is negative - it'll start with a '-' if so
    BOOL negative = NO;
    if(nextChar() == '-')
    {
        negative = YES;
        getAndRemoveCharacter();
    }

    // seed the output number to 0
    double number = 0.0;

    // if the next character isn't a '0' then this is the number proper, so
    // just pull off the digits and assemble the number; otherwise this number
    // is either 0 itself (in which case the initial seed is correct) or a
    // decimal starting in 0
    if(nextChar() != '0')
    {
        while(nextChar() >= '0' && nextChar() <= '9')
        {
            number *= 10.0;
            number += getAndRemoveCharacter() - '0';
        }
    }
    else
        getAndRemoveCharacter();

    // if this is a decimal then jump on to the decimal part and deserialise
    // digits, much as above
    if(nextChar() == '.')
    {
        getAndRemoveCharacter();
        double decimalMultiplier = 1.0;
        while(nextChar() >= '0' && nextChar() <= '9')
        {
            decimalMultiplier /= 10.0;
            number += (double)(getAndRemoveCharacter() - '0') * decimalMultiplier;
        }
    }

    // if this number has an exponent then deal with that
    if(nextChar() == 'e' || nextChar() == 'E')
    {
        getAndRemoveCharacter();

        double exponent = 0.0;
        BOOL exponentPositive = YES;

        // JSON allows positive exponents to start with + (unlike
        // the mantissa) and requires negative exponents to start with -
        if(nextChar() == '+')
        {
            getAndRemoveCharacter();
        }
        else
            if(nextChar() == '-')
            {
                exponentPositive = NO;
                getAndRemoveCharacter();
            }

        // read out digits and assemble exponent
        while(nextChar() >= '0' && nextChar() <= '9')
        {
            exponent *= 10.0;
            exponent += getAndRemoveCharacter() - '0';
        }

        // apply exponent
        number *= pow(10.0, exponentPositive ? exponent : -exponent);
    }

    // negate if necessary and return
    return negative ? -number : number;
}

Any character type that puts the ASCII letters in the normal ASCII range will work, so it should work equally on ASCII and variants, and unicode. I guess you'd probably want to just take a string directly as an argument rather than do all those calls out; they're their in the original because the input stream is coming from afar, so they may block.

The only math.h function used in 'pow', everything else is just primitive operations.

like image 32
Tommy Avatar answered Sep 18 '22 23:09

Tommy