Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Program Only Works If Number Is Printed

Tags:

c++

I am writing a program that can calculate powers of two that are higher than unsigned long long. Basically, I want the program to run and then show the number at the end, but the program only works if I show the number after every time I multiply it by two. Here is the code for the working way:

#include <iostream>
#include <stdio.h>
#include <climits>

using namespace std;

class big {
public:
    short container[SHRT_MAX];
    void print() {
        digits();
        for (; length != 0; length --) {
            cout << container[length - 1];
        }
        cout << "\n";
    }
    unsigned int digits() {
        if (!length) {
            for (length = 0; ; length++) {
                if (container[length] == '\0' &&container[length + 1] == '\0' && container[length + 2] == '\0' && container[length + 3] == '\0' && container[length + 4] == '\0') break;
            }
        }
        return length;
    }
private:
    unsigned int length;
};

int numDigits(int number)
{
    int digits = 0;
    if (number < 0) digits = 1;
    while (number) {
        number /= 10;
        digits++;
    }
    return digits;
}

int main(int argc, const char * argv[])
{
    big result;
    unsigned short tempResult;
    unsigned short carry = 0;
    result.container[0] = 1;

    for (int i = 0; i < 65536; i++) {
        cout << "[" << i+1 << "]\t";
        if (i < 9) {
            cout << "\t";
        }

        carry = 0;
        unsigned int length = result.digits();
        for (int k = 0; k < length; k++) {
            tempResult = result.container[k] * 2 + carry;
            carry = 0;
            if (numDigits(tempResult) == 2) {
                carry = 1;
                result.container[k] = tempResult - 10;
                if (!result.container[k+1] && !result.container[k+2] && !result.container[k+3] && !result.container[k+4]) {
                    result.container[k+1] += carry;
                }
            }
            else {
                result.container[k] = tempResult;
            }
        }
        result.print();
    }
}

I want result.print() to be run after the program is over, not while it is running. I know how to do that, but when I put result.print() outside of the loop the output is 6 and nothing else. Any help would be greatly appreciated and please ask questions if you need clarification.

like image 607
jamespick Avatar asked Sep 15 '13 12:09

jamespick


3 Answers

Your members are being default-initialized, and not value-initialized during construction of your "big" object. Consequently, whatever junk is in that array and length is then being used-as-though-valid when you invoke digits() to compute the length.

Add the following to class big :

big() : length(0) { memset(container, 0, sizeof(container)); }

Even then you still have a stack-overflow issue with the result calculation. This:

if (!result.container[k+1] && !result.container[k+2] && !result.container[k+3] && !result.container[k+4]) {
    result.container[k+1] += carry;

is all-but-guaranteed to overrun your limited digit container for sufficiently large length (and it isn't going to take much).

You're doing literally half your work in this class, and half in code directly modifying members of this class. and violating near-every OOP mantra one can think of. To be completely frank, this needs a redesign badly.

Sample Output (I limited it to 128 entries)

[1]     2
[2]     4
[3]     8
[4]     6
[5]     32
[6]     64
[7]     28
[8]     256
[9]     512
[10]    024
[11]    2048
[12]    4096
[13]    8192
[14]    6384
[15]    32768
[16]    65536
[17]    31072
[18]    262144
[19]    524288
[20]    048576
[21]    2097152
[22]    4194304
[23]    8388608
[24]    6777216
[25]    33554432
[26]    67108864
[27]    34217728
[28]    268435456
[29]    536870912
[30]    073741824
[31]    2147483648
[32]    4294967296
[33]    8589934592
[34]    7179869184
[35]    34359738368
[36]    68719476736
[37]    37438953472
[38]    274877906944
[39]    549755813888
[40]    099511627776
[41]    2199023255552
[42]    4398046511104
[43]    8796093022208
[44]    7592186044416
[45]    35184372088832
[46]    70368744177664
[47]    40737488355328
[48]    281474976710656
[49]    562949953421312
[50]    125899906842624
[51]    2251799813685248
[52]    4503599627370496
[53]    9007199254740992
[54]    8014398509481984
[55]    36028797018963968
[56]    72057594037927936
[57]    44115188075855872
[58]    288230376151711744
[59]    576460752303423488
[60]    152921504606846976
[61]    2305843009213693952
[62]    4611686018427387904
[63]    9223372036854775808
[64]    8446744073709551616
[65]    36893488147419103232
[66]    73786976294838206464
[67]    47573952589676412928
[68]    295147905179352825856
[69]    590295810358705651712
[70]    180591620717411303424
[71]    2361183241434822606848
[72]    4722366482869645213696
[73]    9444732965739290427392
[74]    8889465931478580854784
[75]    37778931862957161709568
[76]    75557863725914323419136
[77]    51115727451828646838272
[78]    302231454903657293676544
[79]    604462909807314587353088
[80]    208925819614629174706176
[81]    2417851639229258349412352
[82]    4835703278458516698824704
[83]    9671406556917033397649408
[84]    9342813113834066795298816
[85]    38685626227668133590597632
[86]    77371252455336267181195264
[87]    54742504910672534362390528
[88]    309485009821345068724781056
[89]    618970019642690137449562112
[90]    237940039285380274899124224
[91]    2475880078570760549798248448
[92]    4951760157141521099596496896
[93]    9903520314283042199192993792
[94]    9807040628566084398385987584
[95]    39614081257132168796771975168
[96]    79228162514264337593543950336
[97]    58456325028528675187087900672
[98]    316912650057057350374175801344
[99]    633825300114114700748351602688
[100]   267650600228229401496703205376
[101]   2535301200456458802993406410752
[102]   5070602400912917605986812821504
[103]   0141204801825835211973625643008
[104]   20282409603651670423947251286016
[105]   40564819207303340847894502572032
[106]   81129638414606681695789005144064
[107]   62259276829213363391578010288128
[108]   324518553658426726783156020576256
[109]   649037107316853453566312041152512
[110]   298074214633706907132624082305024
[111]   2596148429267413814265248164610048
[112]   5192296858534827628530496329220096
[113]   0384593717069655257060992658440192
[114]   20769187434139310514121985316880384
[115]   41538374868278621028243970633760768
[116]   83076749736557242056487941267521536
[117]   66153499473114484112975882535043072
[118]   332306998946228968225951765070086144
[119]   664613997892457936451903530140172288
[120]   329227995784915872903807060280344576
[121]   2658455991569831745807614120560689152
[122]   5316911983139663491615228241121378304
[123]   0633823966279326983230456482242756608
[124]   21267647932558653966460912964485513216
[125]   42535295865117307932921825928971026432
[126]   85070591730234615865843651857942052864
[127]   70141183460469231731687303715884105728
[128]   340282366920938463463374607431768211456
like image 112
WhozCraig Avatar answered Nov 02 '22 07:11

WhozCraig


Your print() and your digits() can work only together.

The digits() calculates a new length only if it is zero. Otherwise it does nothing. The print() function in the place that you write it every iteration makes length equal to 0.

When you move out the printing, length is not equal to 0 at each next iteration, so length stays the same (1 after the first iteration).

Actually it is not a good idea write the print() this way. That means that you can print a number only one time. You should use a local variable for it.

like image 1
Alex Avatar answered Nov 02 '22 08:11

Alex


Okay I am not going to say this is my final solution because I still don't know why that is true, but when I set result.length to 0, I can print the final solution outside of the loop. Here is the code:

#include <iostream>
#include <stdio.h>
#include <climits>

using namespace std;

class big {
public:
    short container[SHRT_MAX];
    void print() {
        digits();
        for (; length != 0; length --) {
            cout << container[length - 1];
        }
        cout << "\n";
    }
    void resetLength() {
        length = 0;
    }
    unsigned int digits() {
        length = 0;
        for (length = 0; ; length++) {
            if (container[length] == '\0' &&container[length + 1] == '\0' && container[length + 2] == '\0' && container[length + 3] == '\0' && container[length + 4] == '\0') break;
        }
        return length;
    }
    big() : length(0) { memset(container, 0, sizeof(container)); }
private:
    unsigned int length;
};

int numDigits(int number)
{
    int digits = 0;
    if (number < 0) digits = 1;
    while (number) {
        number /= 10;
        digits++;
    }
    return digits;
}

int main(int argc, const char * argv[])
{
    big result;
    unsigned short tempResult;
    unsigned short carry = 0;
    result.container[0] = 1;

    for (unsigned int i = 0; i < 65536; i++) {
        /*cout << "[" << i+1 << "]\t";
        if (i < 9) {
            cout << "\t";
        }*/

        carry = 0;
        unsigned int length = result.digits();
        for (int k = 0; k < length; k++) {
            tempResult = result.container[k] * 2 + carry;
            carry = 0;
            if (numDigits(tempResult) == 2) {
                carry = 1;
                result.container[k] = tempResult - 10;
                if (!result.container[k+1] && !result.container[k+2] && !result.container[k+3] && !result.container[k+4]) {
                    result.container[k+1] += carry;
                }
            }
            else {
                result.container[k] = tempResult;
            }
        }
        result.resetLength();
    }
    result.print();
}

Can anyone explain how or why this works?

like image 1
jamespick Avatar answered Nov 02 '22 08:11

jamespick