0

I created a program with a function to convert numbers from a string to a numeric variable (the program will be copied below). I started off using a double; however, for some reason, whenever I built it, it kept rounding the last number up or down if I used decimals. I don't understand why so I would be grateful for any insight you guys could share with me.

#include <iostream>
using namespace std;

//variables initialised in a set of curly brackets are called local variables
//variables initialised outside a set of curly brackets are called global variables
// local variables can only be used in that set of curly brackets
// global variables can be used anywhere after it has been declared
// global variables are automatically set to 0 when it has not been assigned a value
//a void function is a function that returns nothing

//StringName.length() returns the length of a string


/*----------------------------------------FUNCTION-------------------------------------*/
int pow(int a, int b){
int c = 1;
for(int i=0;i<b;i++){
    c*=a;
}
return c;
}

float StringNoToNo(string a){
float b=0.0;
int y = 1;
int s = 0;
//cout<<"a.length() is: "<<a.length()<<endl;
for(int i = (a.length()); i>0;i--){
  //  cout<<"the loop: "<<(a.length()-i)<<endl;
    int z = a[i-1];
    //cout<<"z = "<<z<<endl;
    switch(z){
     case 48 ... 57:
      //    cout<<"(a[i]>=48)&&(a[i]<=57) is true"<<endl;
//cout<<"pow(10.0,(a.length()-i)) = "<<pow(10.0,(a.length()-i))<<endl;
//cout<<"a.length() - i = "<<(a.length()- i)<<endl;
    b += ((a[i-1]-48)* pow(10.0,(a.length()-i-s)));
  //  cout<<"b= "<<b<<endl;
    break;
     case 46:
        y=pow(10,(a.length()-i));
    //    cout<<"y = "<<y<<endl;
        if(s==0){
        s++;}else{
        goto v;
        }
        break;
    default:
        v:
      //  cout<<"(a[i]<48)||(a[i]>57) is true"<<endl;
        cout<< "the number was not written properly"<<endl;
        return 0;
        break;
    }
}
//cout<<" b = "<<b<<endl;
//cout<<"b/y = "<<b/y<<endl;
return (b/y);
}
/*----------------------------------------FUNCTION-------------------------------------*/
// overloading functions - you can create multiple functions with the same name so as long
// as they have different parameters.
// as long as the function is declared at the beginning, even if the function meant to
// overload it is written at the end of the code, it can still be used.

main() {
  string no;
  cout << "write a number: ";
  cin >> no;
  cout << "the number is: "<<StringNoToNo(no)<<endl;
}

At first, I used the double variable for the function and then changed it to float. After that, I used cout at various parts of the loop to see what was going on at every step of the way but still couldn't understand the problem.

The input and output I get are:

write a number: 1234.6789
the number is: 1234.68

Process returned 0 (0x0) execution time : 4.713 s Press any key to continue.

Of course, if I remove the // from the cout functions:

write a number: 1234.6789
the number is: a.length() is: 9
the loop: 0
z = 57
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 1
a.length() - i = 0
b= 9
the loop: 1
z = 56
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 10
a.length() - i = 1
b= 89
the loop: 2
z = 55
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 100
a.length() - i = 2
b= 789
the loop: 3
z = 54
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 1000
a.length() - i = 3
b= 6789
the loop: 4
z = 46
the loop: 5
z = 52
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 100000
a.length() - i = 5
b= 46789
the loop: 6
z = 51
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 1000000
a.length() - i = 6
b= 346789
the loop: 7
z = 50
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 10000000
a.length() - i = 7
b= 2.34679e+06
the loop: 8
z = 49
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 100000000
a.length() - i = 8
b= 1.23468e+07
1234.68

Process returned 0 (0x0)   execution time : 24.055 s
Press any key to continue.
  • Have you checked that `pow` is not overflowing ? – Richard Critten Dec 11 '22 at 12:23
  • 2
    `case 48 ... 57:`? That's not valid C++. Perhaps your compiler have added it as a non-standard and non-portable extension? Besides, please don't use [*magic numbers*](https://en.wikipedia.org/wiki/Magic_number_(programming)). If you want to make sure a character is a digit, use [`std::isdigit`](https://en.cppreference.com/w/cpp/string/byte/isdigit). And `goto`? The way you use it leads to *spaghetti code* which is hard to read and understand and maintain. As a general rule, just don't use `goto`. – Some programmer dude Dec 11 '22 at 12:24
  • And your problem, of creating a floating-point number our of a string can be made much simpler. Especially the integer part. And even simpler when you learn about the [`std::stod`](https://en.cppreference.com/w/cpp/string/basic_string/stof) function. – Some programmer dude Dec 11 '22 at 12:27
  • Please post an example of the input and the output you get. – Bob__ Dec 12 '22 at 09:22
  • @Someprogrammerdude , the '''case 48 ... 57:''' came from the website geeksforgeeks.org/using-range-switch-case-cc thanks for your reply. I understand that there are much easier ways to convert string to float, but for me, this is mainly practice my program works just fine the problem is that it keeps rounding my end result thank you for your reply :) – – Shuayeb Ahmed Dec 12 '22 at 10:01
  • @RichardCritten , what do you mean overflowing? I'm quite new to programming and C++ in general :) thanks for your reply – Shuayeb Ahmed Dec 12 '22 at 10:03
  • @Bob__ i edited my question to involve my input and output :) – Shuayeb Ahmed Dec 12 '22 at 10:04
  • 1
    Please note that geeksforgeeks is not highly regarded around here. It's known to have bad, flawed and sometimes even directly invalid examples. Like that "range switch case". It's *not* a good resource for learning C++. If possible please try to invest in [some good C++ books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282#388282) to learn from instead. – Some programmer dude Dec 12 '22 at 10:12
  • And you still don't need a `switch`, just an `if` to check `std::isdigit(z)`, one `else if` to check for `'.'`, and one `else` for the failure case. – Some programmer dude Dec 12 '22 at 10:13
  • Thanks for replying. Please note that you can increase the number of digits shown in output using [`std::setprecision`](https://en.cppreference.com/w/cpp/io/manip/setprecision) (see e.g.https://godbolt.org/z/d48sdbx5M) and don't forget that [floating-point math is "broken"](https://stackoverflow.com/questions/588004/is-floating-point-math-broken). – Bob__ Dec 12 '22 at 10:16
  • _"..what do you mean overflowing?..."_ `int` can only hold up to a maximum value. If you try to make an `int` hold a larger value than this maximum this is called overflowing. Overflowing an `int` is Undefined Behaviour (a bad thing). Raising a number to a power creates very large numbers very quickly. It is reasonable to check that a power function does not overflow when using a type like `int` which has a limited range see [Fundamental types - Range of values](https://en.cppreference.com/w/cpp/language/types#Range_of_values). – Richard Critten Dec 12 '22 at 11:26

1 Answers1

0

b= 1.23468e+07 proves that your function isn't rounding, it's returning the correct value.

It's actually cout << that's doing the rounding. Use cout << precision(8) to make it display 8 digits of precision instead of the default of 6 digits.

Mooing Duck
  • 64,318
  • 19
  • 100
  • 158