0

I am trying to convert a vector of int to an int. This is how I proceed:

#include <iostream>
#include <cmath>
#include <vector>

using namespace std;

uint32_t toInt(vector<int> v)
{
    uint32_t x=0;
    for(int i=0 ; i<v.size() ; i++)
        x+=v[i]*pow(10, v.size()-1-i);

    return x;
}

int main()
{
    vector<int> v = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    cout << toInt(v) << endl; // displays: 123456787 (???)
}

The program should output 123456789, but instead I have 12345678(!)7(!).

I am using GCC (tdm-1) 4.7.1 on Code::Blocks 13.12

Does someone have an explanation to this problem, and a way to solve it ? Thank you.

Omar Aflak
  • 2,918
  • 21
  • 39
  • [Unable to Reproduce](https://ideone.com/Ia3csX) – Xirema Mar 02 '16 at 17:13
  • [Cannot reproduce](http://ideone.com/JHyqD9) – πάντα ῥεῖ Mar 02 '16 at 17:14
  • [Cannot reproduce](http://coliru.stacked-crooked.com/a/8c6939905f6a28ec) – NathanOliver Mar 02 '16 at 17:14
  • [404: reproduction not found](http://coliru.stacked-crooked.com/a/8c6939905f6a28ec) – Lightness Races in Orbit Mar 02 '16 at 17:24
  • Strange... http://i.imgur.com/nurV2Ez.png?1 – Omar Aflak Mar 02 '16 at 17:24
  • I would suggest that you step through your code and see what is going on then. I do not think we are going to be able to help much. – NathanOliver Mar 02 '16 at 17:26
  • 3
    I bet this has something to do with available `pow` overloads. Knowing your GCC version wouldn't hurt — you should also generally include all this information (including all includes!!) in your questions. – Lightness Races in Orbit Mar 02 '16 at 17:27
  • Noticing that you're in code::blocks 13.12, I wonder if it's a compiler-specific error. That raises the question: what compiler are you using? You're on windows using something identified as GCC, but we don't know details. – WingedPanther73 Mar 02 '16 at 17:28
  • The error appears at the second addition: http://i.imgur.com/1PTJQxY.png?1 – Omar Aflak Mar 02 '16 at 17:30
  • 1
    off topic performance note: `pow` is designed to handle weird stuff like 3.14 to the power of 1/2.78. If you are `pow`ing integers, it's almost always faster to multiply. In this case, `x*=10; x+=v[i];` replaces `x+=v[i]*pow(10, v.size()-1-i);` with far less overhead and fuss (but requires brackets around the body of the `for`). ` – user4581301 Mar 02 '16 at 17:41
  • addendum to @PreferenceBean ;'s comment. Try removing `using namespace std;` or stating `::pow` to force the compiler to use `pow` in place of `std::pow`. – user4581301 Mar 02 '16 at 17:49

3 Answers3

4

I can't imagine it leading to the problem you've cited, but the way you're doing the conversion is pretty ugly, and involves floating point math, so it could lead to at least some degree of inaccuracy in some cases.

You could eliminate that particular problem by doing the conversion a little differently. For example:

int toInt(vector<int> const &v) { // pass by reference to avoid copying
    int ret = 0;
    for (int i=0; i<v.size(); i++)
        ret = 10 * ret + v[i];
    return ret;
}

Or, you could use the standard library to handle more of the work for you:

int toInt(vector<int> const &v) { // pass by reference to avoid copying
    return std::accumulate(v.begin(), v.end(), 
               0, 
               [](int v, int digit) { return 10 * v + digit; });
}

Of course, this is still limited to values that will fit in an int--around 2 billion for a typical 32-bit int, for example.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Thank you, the first one works good for me! I will remember that, even if I still don't understand why the error occurred... – Omar Aflak Mar 02 '16 at 17:38
  • the reason it fails is because floating point number math (pow is floating point) on computers is not exact – pm100 Mar 02 '16 at 19:10
1

The exact cause of this I'm unable to reproduce, but one simple solution is to not use pow:

#include <iostream>
#include <vector>

uint32_t toInt(std::vector<int> v)
{
    uint32_t x=0;
    for(size_t i=0 ; i<v.size() ; i++)
    {
        x*=10; 
        x+=v[i];
    }
    return x;
}

int main()
{
    std::vector<int> v = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    std::cout << toInt(v) << std::endl; 
}

On pow

pow is designed to compute powers of floating point numbers and as a result it does some complex and expensive things. If you are merely getting the power of an integer to an integer, it is almost always faster to multiply.

pow and std::pow are subtly different. std::pow is a templated beast that ultimately calls pow, but only after playing casting games with the input data types and can lead to odd results. Case in point, what this questioner ran into: C++ pow unusual type conversion

This is but one of the many ways using namespace std; can get you. You might be surprised by which pow the compiler selected. Read more here: Why is "using namespace std" considered bad practice?

Community
  • 1
  • 1
user4581301
  • 33,082
  • 7
  • 33
  • 54
0

Your code works fine on my computer

uint32_t toInt(vector<int> v)
{
    uint32_t x=0;
    for(int i=0 ; i<v.size() ; i++)
        x+=v[i]*pow(10, v.size()-1-i);

    return x;
}
int main(){
    int myints[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    vector<int> v (myints, myints + sizeof(myints) / sizeof(int) );
    cout << toInt(v) << endl;
}

which excute like:

./test 123456789 Exit code: 0

This computer is old and runs c++98 but I dont see any reason your program doesn't work. Check your memory for overflow maybe.

idler1515
  • 150
  • 3
  • 11