Search code examples
c++stringparsingdoubledata-conversion

(C++) String to Double converter is inaccurate and totally wrong with negative numbers. What am i doing wrong?


Our teacher gave us this exercise:

"Given a string like '-5,14' write a function that returns the float value of -5,14

I used double here just to test the precision, but it also didn't work with floats.

[also i'm from Europe, we use the comma instead of the dot. Oh also we aren't allowed to use the type string and bool, we have to "make" them like in C]

This is what i came up with, and it seems to work a little bit. Positive numbers are similar, but wrong, and given a negative number, the result is similar to 10 times the positive of the given number.

It should work like this:

  • I read the string into an array of characters;
  • I check if the first character is a minus. if so, subtract 1 from the number of integer figures because i will count them later starting from index 0;
  • I count the number of integer figures with a loop from the start of the array to the ',' character;
  • I count the number of decimal figures with a loop from after the ',' to the end of the string;
  • [Keep in mind for the next step that, following the ASCII table, the code for the character of a number is that number + 48]
  • I add to the result variable every integer figure multiplied by ten to the power of whatever place in the number it has.
  • I do the same for the deicmal values but with the negative exponent.
  • if the number was negative, i multiply the result with -1.

But for some reason it's not working properly. The lower the number is, the less accurate it is (given 4,5 the result is 9, but given 345,543 the result is 350,43)

#include <iostream>

#define EOS '\0'
#define DIM 100

#define TRUE 1
#define FALSE 0

void leggiN(char* c)
{
    std::cout << "Insert a number: ";
    std::cin >> c;
}

double stof(char* str)
{
    double Result = 0;
    double ascii_to_int = 48;

    int i = 0;
    int j = 0;

    int IntegerDigits = 0;
    int DecimalDigits = 0;
    int CommaIndex;

    int isNegative = FALSE;

    if (str[0] == '-')  
    {
        IntegerDigits = -1;
        isNegative = TRUE;
    }

    while (str[i] != ',')   
    {
        ++IntegerDigits;
        ++i;
    }

    CommaIndex = i;  
    ++i;                

    while (str[i] != EOS)   
    {
        ++DecimalDigits;
        ++i;
    }

    for (i = (CommaIndex - 1); i >= 0; --i)
    {
        Result += (str[i] - ascii_to_int) * (std::pow(10, j));
        ++j;
    }

    j = 0;

    for (i = (CommaIndex + 1); str[i] != EOS; ++i)
    {
        Result += (str[i] - ascii_to_int) * (std::pow(10, -j));
        ++j;
    }

    if (isNegative == 1)
        Result = Result * -1;

    return Result;
}

int main()
{
    char str[DIM];

    leggiN(str);

    std::cout << stof(str);
}

Solution

  • use j = 1 to start your second for loop. You are trying to raise 10 to the power of -0

    j = 1;
    
        for (i = (CommaIndex + 1); str[i] != EOS; ++i)
        {
            Result += (str[i] - ascii_to_int) * (std::pow(10, -j));
            ++j;
        }