【问题标题】:Strange: vector<int> to int C++奇怪:vector<int> 到 int C++
【发布时间】:2016-03-02 17:10:03
【问题描述】:

我正在尝试将 int 向量转换为 int。我就是这样进行的:

#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 (???)
}

程序应该输出 123456789,但我有 12345678(!)7(!)。

我在 Code::Blocks 13.12 上使用 GCC (tdm-1) 4.7.1

有人对此问题有解释,以及解决方法吗? 谢谢。

【问题讨论】:

  • 我敢打赌这与可用的pow 重载有关。知道你的 GCC 版本不会有什么坏处——你通常还应该在你的问题中包含所有这些信息(包括所有包含!!)。
  • 离题性能说明:pow 旨在处理 3.14 到 1/2.78 的幂等奇怪的东西。如果您是powing 整数,那么乘法几乎总是更快。在这种情况下,x*=10; x+=v[i]; 替换 x+=v[i]*pow(10, v.size()-1-i); 的开销和麻烦要少得多(但需要在 for 的主体周围加上括号)。 `

标签: c++ vector


【解决方案1】:

我无法想象它会导致您引用的问题,但是您进行转换的方式非常丑陋,并且涉及浮点数学,因此它可能会导致某些情况下至少存在某种程度的不准确案例。

您可以通过稍微不同的转换来消除该特定问题。例如:

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;
}

或者,您可以使用标准库为您处理更多工作:

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; });
}

当然,这仍然限于适合 int 的值——例如,对于典型的 32 位 int,大约为 20 亿。

【讨论】:

  • 谢谢,第一个对我有用!我会记住的,即使我仍然不明白为什么会发生错误......
  • 失败的原因是计算机上的浮点数数学(pow 是浮点数)不准确
【解决方案2】:

我无法重现此问题的确切原因,但一种简单的解决方案是不使用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; 
}

开启pow

pow 旨在计算浮点数的幂,因此它做了一些复杂且昂贵的事情。如果您只是将整数的幂乘以整数,则乘法几乎总是更快。

powstd::pow 略有不同。 std::pow 是一个模板化的野兽,最终会调用pow,但只有在使用输入数据类型玩铸造游戏之后才会导致奇怪的结果。举个例子,这个提问者遇到了什么:C++ pow unusual type conversion

这只是using namespace std; 可以帮助您的众多方式之一。您可能会惊讶于编译器选择了哪个pow。在这里阅读更多:Why is "using namespace std" considered bad practice?

【讨论】:

    【解决方案3】:

    您的代码在我的电脑上运行良好

    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;
    }
    

    执行如下:

    ./测试 123456789 退出代码:0

    这台计算机很旧,运行 c++98,但我看不出您的程序无法运行的任何原因。检查你的内存是否溢出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-16
      • 2013-01-24
      • 1970-01-01
      • 1970-01-01
      • 2023-01-20
      • 2020-01-26
      • 2012-05-03
      相关资源
      最近更新 更多