C++ 程序为某些输入抛出正确的答案,而为其他输入抛出错误的答案。我怀疑数据类型溢出

Posted

技术标签:

【中文标题】C++ 程序为某些输入抛出正确的答案,而为其他输入抛出错误的答案。我怀疑数据类型溢出【英文标题】:C++ program throws right answers for certain inputs and wrong for others. I suspect datatype overflow 【发布时间】:2012-11-20 04:13:33 【问题描述】:

我一直在尝试解决涉及组合学和动态编程的编程挑战。

click here to read the problem

好消息是我已经解决了它,但是对于某些输入,程序会抛出错误的答案。

程序将两个数字作为输入。 让w = argv[1],h = argv[2]

我会用伪数学的方式来写它以便于表示

例如下面的“公式”表示我的程序接受两个参数:w和h,输出为x

T(w,h) = x

我将用T(w,h) 表示理论结果,用R(w, h) 表示我的程序结果。我 100% 确定 T(w, h) 永远是正确答案。

我们走吧:

T(10, 10) = 2R(10, 10) = 2

T(11, 10) = 2R(11, 10) = 288 ** 结果不同 **

T(12, 10) = 4R(12, 10) = 4

T(13, 10) = 4R(13, 10) = 4

T(14, 10) = 66R(14, 10) = 66

T(15, 10) = 290R(15, 10) = 290

T(20, 10) = 9594R(20, 10) = 98826 结果不同

T(25, 10) = 419854R(25, 10) = 419854

T(30, 10) = 94082988R(30, 10) = 94082988

T(35, 10) = 5578404294R(35, 10) = 1283436998 从现在开始,结果总是不同的

T(36, 10) = 19730715436R(36, 10) = 18446744071965430572 数据类型溢出?

T(37, 10) = 19730715436R(37, 10) = 18446744071965430572

T(38, 10) = 73368404198R(38, 10) = 393345822 这个结果比上一个小,应该比上一个大。

T(39, 10) = 287780277370R(39, 10) = 17468538

T(40, 10) = 287780277370R(40, 10) = 17468538

T(41, 10) = 1095232487336R(41, 10) = 15826856

T(42, 10) = 4013757692218 R(42, 10) = 18446744071672822074 再次上升。花费大量时间来计算

我想这对于黑盒测试来说已经足够了,现在让我们看看算法和实际代码。

第一个参数乘以 2,除以 3 并转换为整数。

例如

    argv1 = 20

    20*2 = 40

    40/3 = 13 整数除法

该值被传递给给我带来问题的函数。

iNormalizedWidth 成为那个值。

如果iNormalizedWidth 是奇数,程序会一直给我一个错误的答案。 只给我以下数字的错误答案:

11、20、25、29、35 - 48。

(48 是我的程序将处理的最大值)。

这是我写的函数:

typedef long long int int64; 
#define BLOCK_A = 2;
#define BLOCK_B = 3;

/* main function, more macros, prototypes of other functions and
   irrelevant information for the scope of my question */


vector< vector<int64> > iTileBricks(int iWidth) 
    int iK, i, j, iMaxIterations, iEvenWidth, iOffset;
    vector<int64> viBrickRange;
    vector< vector<int64> > viBrickWall;    
    vector< vector<int64> > viResult;
    iEvenWidth = iWidth % 2;
    iK = (int)(iWidth/2);                                   // The amount of all possible combinations that follow the pattern nCr(iN-i,2i)
    iMaxIterations = iK/3 + 1;                              // By dividing all the possible combinations by 3, I am finding out how the maximum amount of iterations
    for(i = 0; i < iMaxIterations; i++) 
            iOffset = 2*i + iEvenWidth;    
            vector<bool> vAux(iK-i);                        // Creating a iK - i long vector. Test Case:
                                                            // Let  dOriginalPanelWidth = 48
                                                            //      iPanelWidth = 32
                                                            //      iK = iPanelWidth/2 = 16
                                                            //      iMaxIterations = iK/3  ~= 5
                                                            //      iK - i = 16 - i Where 1 <= i <= 5
                                                            //      For the first iteration of i the value of vAux will be: 
            if(iOffset <= iK-i)  
                    fill(vAux.begin() + iOffset, vAux.end(), true); //      For the first iteration of i the value of vAux will be: 
               
                                                            //      vAux = [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
            do                                             // In this block of code I'm generating all the possible layouts of bricks that can build
                    for(j = 0; j < iK-i; j++)              // a wall of 48" (or any value of width where  3 <= width <= 48 and (width % 1/2) == 0). 
                            if(vAux[j] == false) 
                                    viBrickRange.push_back(j);      // Generating n-tuples with all possible combinations
                               
                       
                    viBrickWall.push_back(viBrickRange);
                    viBrickRange.clear();
             while(next_permutation(vAux.begin(), vAux.end()));


            for(unsigned int a=0; a < viBrickWall.size(); a++) 
                    vector<int64> viTmp(iK-i);
                    fill(viTmp.begin(), viTmp.end(), BLOCK_A);
                    for(unsigned int b = 0; b < viBrickWall[a].size(); b++) 
                            viTmp[viBrickWall[a][b]] = BLOCK_B;
                       
                    viResult.push_back(viTmp);
                    viTmp.clear();

               
            viBrickWall.clear();
            vAux.clear();
       
    return viResult;

我找到了一个用python写的程序,后面的函数只不过是从python函数到C++的一个移植而已。如果有帮助,仅供参考:

def all_single_rows(width):
    result = []
    n = width / 2 
    width_parity = width % 2 
    for i in range(n/3 + 1): 
            for bits in combinations(range(n-i), 2*i + width_parity):
                    s = [2] * (n-i)
                    for bit in bits:
                            s[bit] = 3 
                    result.append(s)
    return result

这是一个相当大的功能(和问题),但我整天都在尝试调试它,但我无法提出解决方案。

生成最终值的计算更多,但这是导致其他函数失败的函数。

我想知道关于为什么某些输入的任何理论,答案猛增,然后又回来了。

当我将我的函数与用 python 编写的函数并排比较时 对于某些输入,输出是相同的,而对于其他一些输入(如上所示),输出是不同的。

任何帮助将不胜感激。

非常感谢!

【问题讨论】:

什么是all_single_rows(7) 这是一个用python编写的函数,我想移植到C++ 不,不是“什么是all_single_rows?”,我问的是“什么是all_single_rows(7)”?我不知道python,我在问这个函数返回什么值,如果它是用参数7调用的。 哦,我的错!如果我调用 all_single_rows(7);它返回一个 3 x 3 矩阵:[[3, 2, 2],[2, 3, 2], [2, 2, 3]] 如果我调用我的函数,它会返回一个向量向量:[[3, 2, 2], [2, 3, 2], [2, 2, 3], [3, 3 ]] 【参考方案1】:

我已经解决了这个问题,答案很简单,只是对条件进行了细微的修改。

基本上,我正在生成一组额外的可能组合,为了摆脱它,我需要扩展我的初始条件。

基本上,紧随其后:

vector&lt;bool&gt; vAux(iK-i);

我需要将以下所有说明包含在以下条件中:

if(iOffset &lt;= iK-i)

这解决了我的问题。

感谢大家关注我的问题!

【讨论】:

以上是关于C++ 程序为某些输入抛出正确的答案,而为其他输入抛出错误的答案。我怀疑数据类型溢出的主要内容,如果未能解决你的问题,请参考以下文章

C++编写程序实现小学生数学测验功能

Hystrix Circuit Breaker 是不是可以为某些端点关闭而为其他端点打开

c++程序运行不正确的else语句

vigenere cipher 的 C++ 函数仅有时有效(适用于某些输入,跳过其他输入)

避免 parseInt 为输入字符串抛出 NumberFormatException 的正确方法:“”

在 C++ 中验证来自用户的整数输入