jamespick
jamespick

Reputation: 1978

C++ Program Only Works If Number Is Printed

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.

Upvotes: 6

Views: 2145

Answers (3)

jamespick
jamespick

Reputation: 1978

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?

Upvotes: 1

WhozCraig
WhozCraig

Reputation: 66194

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

Upvotes: 3

Alex
Alex

Reputation: 10126

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.

Upvotes: 1

Related Questions