Rice & Chessboard. Doubling Each Square Problem

J

Jonathan Pritchard

I know this is a simple problem, but I've just included this in the
title because it explains what my program tries to do.

The following does not work, it for someone reason does not want to
place the values on a new line.
=======================================================================
#include <stdio.h>
#include <conio.h>

int main(void)
{
/* Variable delcaration */
long i=1, counter=1, tally=0;

/* Program Body */
do {i = i * 2;
printf("%d \t %d \n", counter, i); /* <======= Here */
++counter;
}
while (counter != 65);
getch();
}
=======================================================================

Whereas the following does work, but all the numbers are in a long line
and not separated. The following does work:

=======================================================================
#include <stdio.h>
#include <conio.h>

int main(void)
{
/* Variable delcaration */
long i=1, counter=1, tally=0;

/* Program Body */
do {i = i * 2;
printf("%d", i); /* <======= Here */
++counter;
}
while (counter != 65);
getch();
}
=======================================================================

I'd really like to know why. Out of curiosity, I don't seem to be doing
anything wrong, to my knowledge. Thanks.
 
W

Walter Roberson

#include <stdio.h>
#include <conio.h>

<conio.h> and getch() are not part of standard C.

It happens this time that we can identify the problem without looking
at those parts.

long i=1, counter=1, tally=0;
printf("%d \t %d \n", counter, i); /* <======= Here */

%d is the format for an int but not for a long. You need %ld for
a long.
 
J

jmcgill

Walter said:
<conio.h> and getch() are not part of standard C.

It happens this time that we can identify the problem without looking
at those parts.




%d is the format for an int but not for a long. You need %ld for
a long.

So why would that suppress the printing of the newline?
 
P

Peter Nilsson

Jonathan said:
I know this is a simple problem, but I've just included this in the
title because it explains what my program tries to do.

The following does not work, it for someone reason does not want to
place the values on a new line.
=======================================================================
#include <stdio.h>
#include <conio.h>

Don't include non-standard headers. There are plenty of alternatives to
putting getch() at the end of the program. [No, I'm not going to tell
you,
that's what Google is for. ;-]
int main(void)
{
/* Variable delcaration */

I know some teachers insist on students putting such comments in code.
Personally, I think they're stupid.
long i=1, counter=1, tally=0;

/* Program Body */
do {i = i * 2;
printf("%d \t %d \n", counter, i); /* <======= Here */

You declared counter and i as _long_ int, but you try to print them as
int using
%d. To print a long int you need to use %ld.

Printing additional space before and after a tab is unusual. Not an
error, but
generally not what you'll want to do. There are ways of making printf
print
an integer within a fixed width field. [RTFM]

Note that the extra space before the newline may be ignored when the
line
is displayed (or piped to file) on some systems.
++counter;
}
while (counter != 65);

A for() loop would be more idiomatic.

Better is just...

return 0;
}
...
Whereas the following does work,

No, it has the same error. Undefined behaviour can do anything,
including
giving the impression that a program works.

I'd really like to know why. Out of curiosity, I don't seem to be doing
anything wrong, to my knowledge.

Expand your knowledge and read the specification of printf.
The function is more powerful and complicated than it looks.
It's easily misused.
 
R

Richard Tobin

Jonathan Pritchard said:
long i=1, counter=1, tally=0;
do {i = i * 2;
printf("%d \t %d \n", counter, i); /* <======= Here */
++counter;
}
while (counter != 65);

Apart from the other problems, unless your longs are very long this
calculation will overflow.

-- Richard
 
J

Jonathan Pritchard

Peter said:
Jonathan said:
I know this is a simple problem, but I've just included this in the
title because it explains what my program tries to do.

The following does not work, it for someone reason does not want to
place the values on a new line.
=======================================================================
#include <stdio.h>
#include <conio.h>

Don't include non-standard headers. There are plenty of alternatives to
putting getch() at the end of the program. [No, I'm not going to tell
you,
that's what Google is for. ;-]
int main(void)
{
/* Variable delcaration */

I know some teachers insist on students putting such comments in code.
Personally, I think they're stupid.
long i=1, counter=1, tally=0;

/* Program Body */
do {i = i * 2;
printf("%d \t %d \n", counter, i); /* <======= Here */

You declared counter and i as _long_ int, but you try to print them as
int using
%d. To print a long int you need to use %ld.

Printing additional space before and after a tab is unusual. Not an
error, but
generally not what you'll want to do. There are ways of making printf
print
an integer within a fixed width field. [RTFM]

Note that the extra space before the newline may be ignored when the
line
is displayed (or piped to file) on some systems.
++counter;
}
while (counter != 65);

A for() loop would be more idiomatic.

Better is just...

return 0;
}
...
Whereas the following does work,

No, it has the same error. Undefined behaviour can do anything,
including
giving the impression that a program works.

I'd really like to know why. Out of curiosity, I don't seem to be doing
anything wrong, to my knowledge.

Expand your knowledge and read the specification of printf.
The function is more powerful and complicated than it looks.
It's easily misused.

Thanks for your criticism. I like to include comments like that, I don't
know why. It's not too much extra hassle.

Yes I worked out it was the wrong data type, well changing the data type
helped. I was using the wrong specifier.

As for "return 0;" I'm afraid it doesn't work for me.

Sorry, shouldn't have posted so quickly. My mistake.
 
D

dcorbit

/*
This program calculates the numbers of rice grains on each square, but
it does not calculate the totals.

It is a simple exercise to get the correct number calculated.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(void)
{
int i;

puts("Double approximation:");
for (i = 0; i < 64; i++)
printf("2^%d = %19.0f\n", i, pow(2.0, (double)i));
puts("\nIntegral version:");
for (i = 0; i < 64; i++)
printf("2^%d = %llu\n", i, 1ULL << i);
return 0;
}
/*
Double approximation:
2^0 = 1
2^1 = 2
2^2 = 4
2^3 = 8
2^4 = 16
2^5 = 32
2^6 = 64
2^7 = 128
2^8 = 256
2^9 = 512
2^10 = 1024
2^11 = 2048
2^12 = 4096
2^13 = 8192
2^14 = 16384
2^15 = 32768
2^16 = 65536
2^17 = 131072
2^18 = 262144
2^19 = 524288
2^20 = 1048576
2^21 = 2097152
2^22 = 4194304
2^23 = 8388608
2^24 = 16777216
2^25 = 33554432
2^26 = 67108864
2^27 = 134217728
2^28 = 268435456
2^29 = 536870912
2^30 = 1073741824
2^31 = 2147483648
2^32 = 4294967296
2^33 = 8589934592
2^34 = 17179869184
2^35 = 34359738368
2^36 = 68719476736
2^37 = 137438953472
2^38 = 274877906944
2^39 = 549755813888
2^40 = 1099511627776
2^41 = 2199023255552
2^42 = 4398046511104
2^43 = 8796093022208
2^44 = 17592186044416
2^45 = 35184372088832
2^46 = 70368744177664
2^47 = 140737488355328
2^48 = 281474976710656
2^49 = 562949953421312
2^50 = 1125899906842624
2^51 = 2251799813685248
2^52 = 4503599627370496
2^53 = 9007199254740992
2^54 = 18014398509481984
2^55 = 36028797018963968
2^56 = 72057594037927936
2^57 = 144115188075855870
2^58 = 288230376151711740
2^59 = 576460752303423490
2^60 = 1152921504606847000
2^61 = 2305843009213694000
2^62 = 4611686018427387900
2^63 = 9223372036854775800

Integral version:
2^0 = 1
2^1 = 2
2^2 = 4
2^3 = 8
2^4 = 16
2^5 = 32
2^6 = 64
2^7 = 128
2^8 = 256
2^9 = 512
2^10 = 1024
2^11 = 2048
2^12 = 4096
2^13 = 8192
2^14 = 16384
2^15 = 32768
2^16 = 65536
2^17 = 131072
2^18 = 262144
2^19 = 524288
2^20 = 1048576
2^21 = 2097152
2^22 = 4194304
2^23 = 8388608
2^24 = 16777216
2^25 = 33554432
2^26 = 67108864
2^27 = 134217728
2^28 = 268435456
2^29 = 536870912
2^30 = 1073741824
2^31 = 2147483648
2^32 = 4294967296
2^33 = 8589934592
2^34 = 17179869184
2^35 = 34359738368
2^36 = 68719476736
2^37 = 137438953472
2^38 = 274877906944
2^39 = 549755813888
2^40 = 1099511627776
2^41 = 2199023255552
2^42 = 4398046511104
2^43 = 8796093022208
2^44 = 17592186044416
2^45 = 35184372088832
2^46 = 70368744177664
2^47 = 140737488355328
2^48 = 281474976710656
2^49 = 562949953421312
2^50 = 1125899906842624
2^51 = 2251799813685248
2^52 = 4503599627370496
2^53 = 9007199254740992
2^54 = 18014398509481984
2^55 = 36028797018963968
2^56 = 72057594037927936
2^57 = 144115188075855872
2^58 = 288230376151711744
2^59 = 576460752303423488
2^60 = 1152921504606846976
2^61 = 2305843009213693952
2^62 = 4611686018427387904
2^63 = 9223372036854775808
*/
 
D

dcorbit

/* The devil made me do it. */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

typedef struct riceconv {
double qty;
const char *unit;
const char *desc;
} riceconv;

riceconv rcunits[] =
{
{37., "grams", "37 = Grains of rice per gram"},
{36590., "kilograms", "36,590 = Grains of rice per kilogram"},
{36589830., "metric tons", "36,589,830 = Grains of rice per metric
ton"},
{36589830000000., "million metric tons", "36,589,830,000,000 =
Grains of rice per million metric tons"}
};

extern char *fmt_money(double amt);
static void form_group(int amt, char *scale);

/*
** FMTMONEY.C - Format a U.S. dollar value into a numeric string
**
** public domain demo by Bob Stout
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#define Form(s,a) bufptr += sprintf(bufptr, s, a)

static char buf[256],
*bufptr;

static char *units[] = {"Zero", "One", "Two", "Three", "Four",
"Five", "Six", "Seven", "Eight", "Nine",
"Ten", "Eleven", "Twelve", "Thirteen", "Fourteen",
"Fifteen", "Sixteen", "Seventeen", "Eighteen",
"Nineteen"},

*tens[] = {"Twenty", "Thirty", "Forty", "Fifty",
"Sixty",
"Seventy", "Eighty", "Ninety"};

static void form_group(int, char *);

/*
** Call with double amount
** Rounds cents
** Returns string in a static buffer
*/

char *fmt_money(double amt)
{
int temp;
double dummy,
cents = modf(amt, &dummy);

*buf = '\0';
bufptr = buf;

temp = (int) (amt / 1E12);
if (temp) {
form_group(temp, "Trillion");
amt = fmod(amt, 1E12);
}
temp = (int) (amt / 1E9);
if (temp) {
form_group(temp, "Billion");
amt = fmod(amt, 1E9);
}
temp = (int) (amt / 1E6);
if (temp) {
form_group(temp, "Million");
amt = fmod(amt, 1E6);
}
temp = (int) (amt / 1E3);
if (temp) {
form_group(temp, "Thousand");
amt = fmod(amt, 1E3);
}
form_group((int) amt, "");

if (buf == bufptr)
Form("%s ", units[0]);

temp = (int) (cents * 100. + .5);
sprintf(bufptr, "& %02d/100", temp);

return buf;
}

/*
** Process each thousands group
*/

static void form_group(int amt, char *scale)
{
if (buf != bufptr)
*bufptr++ = ' ';

if (100 <= amt) {
Form("%s Hundred ", units[amt / 100]);
amt %= 100;
}
if (20 <= amt) {
Form("%s", tens[(amt - 20) / 10]);
if (0 != (amt %= 10)) {
Form("-%s ", units[amt]);
} else
Form("%s", " ");
} else if (amt) {
Form("%s ", units[amt]);
}
Form("%s", scale);
}
int main(void)
{
int i;
unsigned long long total = 0;

puts("\nIntegral version:");
for (i = 0; i < 64; i++) {
printf("For square %d we calculate:\n", i + 1);
printf("2^%d = %llu grains on this square\n", i, 1ULL << i);
total += 1ULL << i;
printf("Total for all squares so far is %llu\n", total);
}
puts("That total is:");
for (i = 0; i < 4; i++) {
printf("%20.18g %s of rice\n", total / rcunits.qty,
rcunits.unit);
if (i < 3)
puts("or");
}
puts("That's a lot of rice.\n");
printf("If you ate one kilogram of rice per day, it would take
you:\n %s years to eat it all.\n\n", fmt_money((total / 36590.) /
365.25636042));
puts("If you lived that long, and you managed to eat it all, I bet
you would be sick of rice.");
return 0;
}
 
T

Tak-Shing Chan

On Tue, 11 Sep 2006 (e-mail address removed) wrote:

[snip]
int main(void)
{
int i;
unsigned long long total = 0;

puts("\nIntegral version:");
for (i = 0; i < 64; i++) {
printf("For square %d we calculate:\n", i + 1);
printf("2^%d = %llu grains on this square\n", i, 1ULL << i);
total += 1ULL << i;
printf("Total for all squares so far is %llu\n", total);
}
puts("That total is:");
for (i = 0; i < 4; i++) {
printf("%20.18g %s of rice\n", total / rcunits.qty,
rcunits.unit);
if (i < 3)
puts("or");
}
puts("That's a lot of rice.\n");
printf("If you ate one kilogram of rice per day, it would take
you:\n %s years to eat it all.\n\n", fmt_money((total / 36590.) /
365.25636042));
puts("If you lived that long, and you managed to eat it all, I bet
you would be sick of rice.");
return 0;
}


Why not simply:

#include <stdio.h>

int main(void)
{
int i;

for (i = 1; i < 65; i++)
printf("Total (up to square %d) = %llu\n", i,
18446744073709551615ULL >> 64 - i);
return 0;
}

Tak-Shing
 
B

Barry Schwarz

So why would that suppress the printing of the newline?

Because when you invoke undefined behavior anything can happen. You
lied to printf and it is not surprising that it got confused enough
not to print the \n.


Remove del for email
 
B

Barry Schwarz

/*
This program calculates the numbers of rice grains on each square, but
it does not calculate the totals.

It is a simple exercise to get the correct number calculated.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(void)
{
int i;

puts("Double approximation:");
for (i = 0; i < 64; i++)
printf("2^%d = %19.0f\n", i, pow(2.0, (double)i));

Since a prototype for pow is in scope, the cast on i serves no
purpose.

If you change the %d to %02d, your output will line up neatly.
puts("\nIntegral version:");
for (i = 0; i < 64; i++)
printf("2^%d = %llu\n", i, 1ULL << i);
return 0;
}
/*
Double approximation:
2^0 = 1
2^1 = 2
2^2 = 4
2^3 = 8
2^4 = 16
2^5 = 32
2^6 = 64
2^7 = 128
2^8 = 256
2^9 = 512
2^10 = 1024
2^11 = 2048
2^12 = 4096
2^13 = 8192
2^14 = 16384
2^15 = 32768
2^16 = 65536
2^17 = 131072
2^18 = 262144
2^19 = 524288
2^20 = 1048576
2^21 = 2097152
2^22 = 4194304
2^23 = 8388608
2^24 = 16777216
2^25 = 33554432
2^26 = 67108864
2^27 = 134217728
2^28 = 268435456
2^29 = 536870912
2^30 = 1073741824
2^31 = 2147483648
2^32 = 4294967296
2^33 = 8589934592
2^34 = 17179869184
2^35 = 34359738368
2^36 = 68719476736
2^37 = 137438953472
2^38 = 274877906944
2^39 = 549755813888
2^40 = 1099511627776
2^41 = 2199023255552
2^42 = 4398046511104
2^43 = 8796093022208
2^44 = 17592186044416
2^45 = 35184372088832
2^46 = 70368744177664
2^47 = 140737488355328
2^48 = 281474976710656
2^49 = 562949953421312
2^50 = 1125899906842624
2^51 = 2251799813685248
2^52 = 4503599627370496
2^53 = 9007199254740992
2^54 = 18014398509481984
2^55 = 36028797018963968
2^56 = 72057594037927936
2^57 = 144115188075855870
2^58 = 288230376151711740
2^59 = 576460752303423490
2^60 = 1152921504606847000
2^61 = 2305843009213694000
2^62 = 4611686018427387900
2^63 = 9223372036854775800

Integral version:
2^0 = 1
2^1 = 2
2^2 = 4
2^3 = 8
2^4 = 16
2^5 = 32
2^6 = 64
2^7 = 128
2^8 = 256
2^9 = 512
2^10 = 1024
2^11 = 2048
2^12 = 4096
2^13 = 8192
2^14 = 16384
2^15 = 32768
2^16 = 65536
2^17 = 131072
2^18 = 262144
2^19 = 524288
2^20 = 1048576
2^21 = 2097152
2^22 = 4194304
2^23 = 8388608
2^24 = 16777216
2^25 = 33554432
2^26 = 67108864
2^27 = 134217728
2^28 = 268435456
2^29 = 536870912
2^30 = 1073741824
2^31 = 2147483648
2^32 = 4294967296
2^33 = 8589934592
2^34 = 17179869184
2^35 = 34359738368
2^36 = 68719476736
2^37 = 137438953472
2^38 = 274877906944
2^39 = 549755813888
2^40 = 1099511627776
2^41 = 2199023255552
2^42 = 4398046511104
2^43 = 8796093022208
2^44 = 17592186044416
2^45 = 35184372088832
2^46 = 70368744177664
2^47 = 140737488355328
2^48 = 281474976710656
2^49 = 562949953421312
2^50 = 1125899906842624
2^51 = 2251799813685248
2^52 = 4503599627370496
2^53 = 9007199254740992
2^54 = 18014398509481984
2^55 = 36028797018963968
2^56 = 72057594037927936
2^57 = 144115188075855872
2^58 = 288230376151711744
2^59 = 576460752303423488
2^60 = 1152921504606846976
2^61 = 2305843009213693952
2^62 = 4611686018427387904
2^63 = 9223372036854775808
*/


Remove del for email
 
D

dcorbit

Tak-Shing Chan said:
On Tue, 11 Sep 2006 (e-mail address removed) wrote:

[snip]
int main(void)
{
int i;
unsigned long long total = 0;

puts("\nIntegral version:");
for (i = 0; i < 64; i++) {
printf("For square %d we calculate:\n", i + 1);
printf("2^%d = %llu grains on this square\n", i, 1ULL << i);
total += 1ULL << i;
printf("Total for all squares so far is %llu\n", total);
}
puts("That total is:");
for (i = 0; i < 4; i++) {
printf("%20.18g %s of rice\n", total / rcunits.qty,
rcunits.unit);
if (i < 3)
puts("or");
}
puts("That's a lot of rice.\n");
printf("If you ate one kilogram of rice per day, it would take
you:\n %s years to eat it all.\n\n", fmt_money((total / 36590.) /
365.25636042));
puts("If you lived that long, and you managed to eat it all, I bet
you would be sick of rice.");
return 0;
}


Why not simply:

#include <stdio.h>

int main(void)
{
int i;

for (i = 1; i < 65; i++)
printf("Total (up to square %d) = %llu\n", i,
18446744073709551615ULL >> 64 - i);
return 0;
}

Tak-Shing


Well, besides the missing subtotals, it also fails to tell me how long
it's going to take to eat it. It also might be fun to find out how
much it weighs and also how many cubic feet it would occupy.
 
D

dcorbit

Barry said:
Since a prototype for pow is in scope, the cast on i serves no
purpose.

It quiets a useless warning.
If you change the %d to %02d, your output will line up neatly.

The double version is the wrong way to do it anyway.
[snip]
 
T

Tak-Shing Chan

Tak-Shing Chan said:
On Tue, 11 Sep 2006 (e-mail address removed) wrote:

[snip]
int main(void)
{
int i;
unsigned long long total = 0;

puts("\nIntegral version:");
for (i = 0; i < 64; i++) {
printf("For square %d we calculate:\n", i + 1);
printf("2^%d = %llu grains on this square\n", i, 1ULL << i);
total += 1ULL << i;
printf("Total for all squares so far is %llu\n", total);
}
puts("That total is:");
for (i = 0; i < 4; i++) {
printf("%20.18g %s of rice\n", total / rcunits.qty,
rcunits.unit);
if (i < 3)
puts("or");
}
puts("That's a lot of rice.\n");
printf("If you ate one kilogram of rice per day, it would take
you:\n %s years to eat it all.\n\n", fmt_money((total / 36590.) /
365.25636042));
puts("If you lived that long, and you managed to eat it all, I bet
you would be sick of rice.");
return 0;
}


Why not simply:

#include <stdio.h>

int main(void)
{
int i;

for (i = 1; i < 65; i++)
printf("Total (up to square %d) = %llu\n", i,
18446744073709551615ULL >> 64 - i);
return 0;
}

Tak-Shing


Well, besides the missing subtotals, it also fails to tell me how long
it's going to take to eat it. It also might be fun to find out how
much it weighs and also how many cubic feet it would occupy.


Well, my code does print all the subtotals. As for how
long it's going to take to eat it: keep in mind that the rice
might not survive that long in storage!

Tak-Shing
 
J

Joe Wright

Jonathan said:
I know this is a simple problem, but I've just included this in the
title because it explains what my program tries to do.

The following does not work, it for someone reason does not want to
place the values on a new line.
=======================================================================
#include <stdio.h>
#include <conio.h>

int main(void)
{
/* Variable delcaration */
long i=1, counter=1, tally=0;

/* Program Body */
do {i = i * 2;
printf("%d \t %d \n", counter, i); /* <======= Here */
++counter;
}
while (counter != 65);
getch();
}
=======================================================================

Whereas the following does work, but all the numbers are in a long line
and not separated. The following does work:

=======================================================================
#include <stdio.h>
#include <conio.h>

int main(void)
{
/* Variable delcaration */
long i=1, counter=1, tally=0;

/* Program Body */
do {i = i * 2;
printf("%d", i); /* <======= Here */
++counter;
}
while (counter != 65);
getch();
}
=======================================================================

I'd really like to know why. Out of curiosity, I don't seem to be doing
anything wrong, to my knowledge. Thanks.

Lots wrong. First, conio.h is not Standard C (the subject here). In the
general case, long is 32 bits and not wide enough for i and tally.

#include <stdio.h>

int main(void) {
unsigned long long i = 1, tally = 1;
int counter = 1;
do {
printf("%3d%21llu%21llu\n", counter, i, tally);
i *= 2;
tally += i;
++counter;
} while (counter < 65);
return 0;
}
 
J

Jonathan Pritchard

Joe said:
Lots wrong. First, conio.h is not Standard C (the subject here). In the
general case, long is 32 bits and not wide enough for i and tally.

#include <stdio.h>

int main(void) {
unsigned long long i = 1, tally = 1;
int counter = 1;
do {
printf("%3d%21llu%21llu\n", counter, i, tally);
i *= 2;
tally += i;
++counter;
} while (counter < 65);
return 0;
}

Sorry, sometimes it's the only thing that works, to hold the output on
screen. Thanks for the above listing. I'll look into the unsigned long
long data type.
 
K

Keith Thompson

Jonathan Pritchard said:
Joe said:
Jonathan Pritchard wrote: [...]
#include <conio.h> [...]
getch();
[...]
Lots wrong. First, conio.h is not Standard C (the subject here).
Sorry, sometimes it's the only thing that works, to hold the output on
screen.
[...]

No, getch() isn't the only way to hold the output on the screen.

Assuming you're using MS Windows, you can execute the program from a
command window, or your IDE probably provides a way to execute a
program without closing the window as soon as it's finished.

Or you can replace the call to getch() with a call to getchar().
(Print a message first if you like.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top