Omar Aflak
Omar Aflak

Reputation: 2962

Strange: vector<int> to int C++

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.

Upvotes: 0

Views: 122

Answers (3)

user4581301
user4581301

Reputation: 33962

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?

Upvotes: 1

idler1515
idler1515

Reputation: 150

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.

Upvotes: 0

Jerry Coffin
Jerry Coffin

Reputation: 490623

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.

Upvotes: 4

Related Questions