# Number cubed?

I had a Pascal exam few days ago and I had no idea how to do the last problem, which is:
Make a program which asks you to introduce a number. For example, if you typed 3, the program will do the sum of "1 cubed + 2 cubed + 3 cubed". No matter how I did, I couldn't make this work.

• If I have understood correctly:
[code]
program cubes;
var num, i: byte;
sum: longint;
begin
sum := 0;
Writeln ('Introduce a number: ');
for i := 1 to num do
sum := sum + i*i*i;
Writeln (sum);
end.
[/code]
• Yes, that's right. T_T
I almost made it, just a few mistakes. Thank you!
• I'm not 100% sure what you mean either, but maybe it's something along these lines:
sum = [1^n + 2^n + .. +n^n]...

[code]
program sequence;
var
i, n, count, sum: integer;

function power(index: integer): integer;
var
j, product: integer;
begin
product := 1;
for j := 1 to n do
product := product * index;
writeln(product);
power := product;
end;

begin
writeln('Enter a value for ''n'': ');

count := 1;
for i := 1 to n do
begin
sum := sum + power(count);
count := succ(count);
end;
writeln;
writeln(sum);

end.
[/code]

There's probably a more elegant way to do it, though.
• : If I have understood correctly:
: [code]:
: program cubes;
: var num, i: byte;
: sum: longint;
: begin
: sum := 0;
: Writeln ('Introduce a number: ');
: for i := 1 to num do
: sum := sum + i*i*i;
: Writeln (sum);
: end.
: [/code]:

This may gives you issues because you are using:
[code]i*i*i
[/code]
[b]i[/b] is declared as a byte, so if you have 7*7*7 > 255 (size of byte) I believe it returns a byte value 87 (343-256) and therefore incorrect. You could just declare [b]i[/b] as a larger value (WORD or LONGINT) or override each [b]i[/b] like so:
[code]Word(i)*Word(i)*Word(i)
[/code]
Since there is no reason that [b]i[/b] mMUST be a byte, it's just easier to change it to a Word/LongInt.
• Thank you for notice. I am beginner in programming. Maybe, you can explain why this happens (max sum is larger but max i is smaller than i*i*i, there is overflow) in Pascal(perhaps in other languages too)
How it works?
• : How it works?

You can blame Pascal's strong typing for the overflow :-). Like Phat Nat pointed out, when you perform operations with a type of variable care must be taken for the result to be within the boundary of that type, if you think that it will be beyond then step up that type to a bigger ranged one. For example:[code][color=Blue]var i:byte;

i:=100;
i:=i+i+i; {<-- overflow here}
{Because a byte can hold a value in the 0..255 range only, so 100+100+100 is beyond that.}

-OR-

i:=100;
i:=50-i; {<-- another overflow, a byte cannot be negative}[/color][/code]By changing [b]i[/b] to [b]integer[/b] these examples will work correctly because an integer is in range of -32768..32767.
• You are right. But I would like to know why I may get overflow with this expression:
[code]
sum := sum + i*i*i
[/code]

as with this?
[code]
i := i*i*i;
sum := sum + i
[/code]
• First of all, the operators get evaluated in a certain order ( lookup TP's help for more info), so:[code]sum:=sum + i*i*i
is evaluated as:
longint=longint + byte*byte*byte[/code]Because [b]*[/b] goes before [b]+[/b], will multiply the three bytes first then will add to the longint. The multiplications are restricted to a byte type ([b]i[/b], the aforementioned strong typing of Pascal...), so the result will be stored in a byte. I'm not sure if this made sense, but imagine to do a math. operation on paper and you are restricted to let's say 3 digits, now with additions or multiplications soon the result will grow over the range what 3 digits are capable to hold, this is an overflow, your result is 4 digit (decimal) and you're able to show only 3. Because the computer handles binary numbers the values over your range will wrap around, (same thing how a car's odometer would turn to 0 after passing 99999....) eg:[code]var i:byte;
i:=250;
i:=i+20;
{now we would expect i to be equal to 270, but because this is above
the [0..255] range, i will be equal to 270-256}

This is correct ( as long as w*i is in the 16 bit range ):
var w:word;
w:=w * i;
{Doing a math. operations between 2 compatible types, the result must fit within the range of the bigger type,
[0..65535] in this example}[/code]
• It is clear now. Thank you very much
• : : How it works?
:
: You can blame Pascal's strong typing for the overflow :-).

Actually the overflow is due to Pascal's [u]lack[/u] of strong typing. Although Pascal is one of the most strongly typed languages around, it is not as strongly typed as it could be. Niklaus Witth, the creator of Pascal, covers this issue in his book [italic]Systematic Programming: An Introduction[/italic]. An absolutely strongly typed language would create a range error if [b]i[/b] is of type byte and [b]i*i*i[/b] evaluated to more than 255. Instead, Pascal uses clock arithmetic, sometimes allows a mix of types in an expression, and does not flag out of range results. This bug will still be there if you use type LongInt, and in many cases incorrect errors will not be readily evident.
• : ... Pascal's [u]lack[/u] of strong typing....
: ... is one of the most strongly typed languages around ...

Aren't those sentences contradicting each-other ? Yeah, I know, "strong" is relative and just a definition of some point of view...:-)

: [italic]Systematic Programming: An Introduction[/italic].

Don't forget this book was published in 1973, today's Pascal is not what used to be then, every reference to Pascal should be taken with a grain of salt. Beside that, it's a really good book, I strongly recommend it to anybody serious about programming.

: absolutely strongly typed language would create a range error if

Interestingly, TP has a compiler directive for that (\$Q) ( same for Free Pascal but I guess is there only for compatibility issues only...) BTW, to my surprise was no overflow with that given code piece (...sum+ i*i*i...) with overflow check on or off, no overflow with Free Pascal as well. Anyway one should always use a debugger and practice careful coding....

[color=Red]Correction:[code]{\$Q+} {Flag out of range results}
var i:byte;
sum:longint;
i:=i*i*i; <-- Will cause an overflow, given the result is beyond i's range
sum:=sum + i*i*i; <-- Will not cause an overflow, given the result is less than sum's range[/code]The cause is the memory allocation for that particular operation and type ( ie strong typing...).[/color]
• : : ... Pascal's [u]lack[/u] of strong typing....
: : ... is one of the most strongly typed languages around ...
:
: Aren't those sentences contradicting each-other ?

[blue]
Omitting the phrase that follows means you're quoting me out of context.
[/blue]

: : [italic]Systematic Programming: An Introduction[/italic].
:
: Don't forget this book was published in 1973,
[blue]
All the really good programming books were written decades ago. ;-)
[/blue]
: today's Pascal is not what used to be then,
[blue]
Thank God!! :-) ... and the American National Standards Institute and the Institute of Electrical and Electronics Engineers.
[/blue]

• This is a bit of a digression. This is a program from Kernighan and Plauger's [italic]Software Tools in Pascal[/italic]. They declare a variable [b]cur[/b] to be a subrange [b]0 .. 1[/b], then in a loop they repeatedly decrement it. If you examine the code it's obvious that they expect the value to flip flop between 0 and 1. Kind of neat. I have not tried this, but it must work since the entire books emphasizes code that does not dependent on the quirks of any particular implementation of Pascal.
[code]
{ Copyright (C) 1981 by Bell Laboratories, Inc., and Whitesmiths Ltd. }
{ unique -- remove adjacent duplicate lines }
procedure unique;
var
buf : array [0..1] of string;
[red]cur : 0..1;[/red]
begin
cur := 1;
buf[1-cur][1] := ENDSTR;
while (getline(buf[cur], STDIN, MAXSTR)) do
if (not equal(buf[cur], buf[1-cur])) then begin
putstr(buf[cur], STDOUT);
[red]cur := 1 - cur[/red]
end
end;
[/code]
I wonder though, if this code is not counter to the philosophy K&P espouse in their earlier book [italic]The Elements of Programming Style[/italic], namely "don't write tricky code."
• The code works ( at least the cur:=1-cur; part of it, didn't test the rest...), it's a neat way to flip between 0 and 1, I'm not sure but it probably could be adapted to flip between different values as well. Mathematically:[code][blue]if: f(x)=1-x
then: for x=0 --> f(x)=1
and x=1 --> f(x)=0[/blue][/code]I guess this would be the fastest way to swap 0 and 1, maybe other values too...

Another interesting feature of TP, is that ranged variables:[code][blue]var c:1..10;[/code]do not wrap like would be expected to do, TP rather assigns the smallest ordinal type what that ranged var. fits ( in this case a shotint ), and treats all the operations accordingly. The only difference is that the programmer cannot assign a value directly which is out the range:[code][blue]var i:byte;
c:1..10;
c:=11; {<-- Constant out of range error (upon compiling )}
i:=11;
c:=i; {<-- No error here, even with \$Q+}[/code] Wrapping example:[code][blue]{\$Q+} {Range checking on}
uses crt;
var c:1..10;
begin
c:=1;
while not keypressed do begin
writeln(c);
inc(c); {<-- Doesn't flag range check, c:=c+1; neither }
delay(50); {<-- a short pause so we can see the changes}
end;