Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

4294967295 * 4294967295 = 1

55 views
Skip to first unread message

salvador

unread,
Aug 25, 2005, 4:43:16 PM8/25/05
to
procedure TForm1.Button1Click(Sender: TObject);
var
UInit64: TULargeInteger; // TULargeInteger = ULARGE_INTEGER
windows.pas
Cardinal1,Cardinal2 : Cardinal; // Cardinal 0 .. 4294967295;
begin
Cardinal1 := High(Cardinal); // Cardinal1 --> 4294967295;
Cardinal2 := High(Cardinal); // Cardinal2 --> 4294967295;
UInit64.QuadPart := Cardinal1 * Cardinal2; // 4294967295 * 4294967295 =
18446744065119617025 ;
Caption := IntToStr(UInit64.QuadPart); // caption = 1
// 4294967295 * 4294967295 = 18446744065119617025 but caption = 1
end;


Guenther Wimpassinger

unread,
Aug 25, 2005, 5:15:08 PM8/25/05
to

"salvador" <salv...@gmail.com> schrieb


two things:
+)operations with integer-values (<=32bit) are always calculated
with 32bits. you only have 64bit calculations if one of the
operands has 64bit. Both Cardinal1 and 2 are 32bit, so the
result is 32bit too. you have to typecast one of the operands.

the assignment is a different operation to the multiplication.

+)delphi do not handle unsigned 64bit integers. At lest until
D7. Don't know for D2005 (Win32).

this code:

procedure TForm1.Button1Click(Sender: TObject);
var
i64 : Int64; // the QuadPart of TULargeInteger => int64
b1,b2 : Byte;
C1,C2 : LongWord;
begin
C1 := High(C1);
C2 := High(C2);
i64 := C1 * C2;
ListBox1.Items.Add(IntToStr(i64));
i64 := int64(C1) * C2;
ListBox1.Items.Add(IntToStr(i64));
b1 := High(b1);
b2 := High(b2);
i64 := b1 * b2;
ListBox1.Items.Add(IntToStr(i64));
end;

produce this results:
1
-8589934591
65025

in D7.


John Herbster

unread,
Aug 25, 2005, 8:45:58 PM8/25/05
to

"salvador" <salv...@gmail.com> wrote
> ...
Cardinal1 := High(Cardinal);
Cardinal2 := High(Cardinal);

UInit64.QuadPart := Cardinal1 * Cardinal2;
> ...

"1"? I get the Integer Overflow exception!
I notice that the QuadPart is an Int64 variable
-- thus the overflow.
Do you maybe have overflow checking turned off?
Further, note that in Delphi's arithmetic, the result of any
two-operand arithmetic multiplication the intermediate
result will be the type of the largest (in size) operand
-- thus Cardinal1*Cardinal2 will overflow if the result
exceeds 32 bits. A way around this is to write the
expression as Int64(Cardinal1)*Cardinal2. This is
called a "value typecast". With this, you can do
Cardinal1 := High(Cardinal);
Cardinal2 := High(Cardinal) div 2;
UInit64.QuadPart := Int64(Cardinal1) * Cardinal2;
--JohnH

Guenther Wimpassinger

unread,
Aug 26, 2005, 5:13:56 AM8/26/05
to

"John Herbster" <herb-sci1_AT_sbcglobal.net> schrieb
Hi John!


> Further, note that in Delphi's arithmetic, the result of any
> two-operand arithmetic multiplication the intermediate
> result will be the type of the largest (in size) operand

Are you sure?

This is from the Delphi (7) Language Guide (Ch. 5 / Integer Types)
from Borland
-----------------
In general, arithmetic operations on integers return
a value of type Integer—which, in its current implementation,
is equivalent to the 32-bit Longint. Operations return a
value of type Int64 only when performed on one or more
Int64 operand.
-----------------

And during the test multiplying two byte variables results in
a 32 bit value.

bye
Guenther

John Herbster

unread,
Aug 26, 2005, 8:28:44 AM8/26/05
to

"Guenther Wimpassinger" <gw_...@pickem.at> wrote

> > Further, note that in Delphi's arithmetic, the result of any
> > two-operand arithmetic multiplication the intermediate
> > result will be the type of the largest (in size) operand

> Are you sure?

> This is from the Delphi (7) Language Guide (Ch. 5 / Integer Types)
> from Borland
> -----------------
> In general, arithmetic operations on integers return
> a value of type Integer—which, in its current implementation,
> is equivalent to the 32-bit Longint. Operations return a
> value of type Int64 only when performed on one or more
> Int64 operand.
> -----------------

> And during the test multiplying two byte variables results in
> a 32 bit value.

No, I am not sure. The help documentation is not clear in its
use of integer (vs. signed 32-bit integer). Nor am I sure what
will happen to the intermediate results of multiplies or the
sqr() function when the default integer becomes 64 bits.

In QC#5743 "SQR function failures (a summary)" there used
to be some comments (by Danny Thorpe, I think) stating that
the result of the "sqr(i)" operations should be the same as the
results of "i*i", but for some reason these comments have
since been removed.

I based my answer on the since expunged comments and
the following information in the description section of
QC#5743:

"The SQR function fails when the argument is near the
top of the range of the input variable.
Result = sqr(<byte variable>) gives Range check error
Result = sqr(<Word variable>) gives wrong result
Result = sqr(<DWord variable>) gives wrong result
Result = sqr(<Cardinal variable>) gives wrong result
Result = sqr(<ShortInt variable>) gives *correct* result
Result = sqr(<SmallInt variable>) gives wrong result
Result = sqr(<LongInt variable>) gives wrong result
Result = sqr(<Integer variable>) gives wrong result

If it is really important that your code last a long time,
I suggest practicing defensive programming in this area
and using:
result := operand1;
result := result*operand2;

Thanks for bringing this up, JohnH

Lord Crc

unread,
Aug 26, 2005, 8:47:23 AM8/26/05
to
On Fri, 26 Aug 2005 07:28:44 -0500, "John Herbster"
<herb-sci1_AT_sbcglobal.net> wrote:

>In QC#5743 "SQR function failures (a summary)" there used
>to be some comments (by Danny Thorpe, I think) stating that
>the result of the "sqr(i)" operations should be the same as the
>results of "i*i", but for some reason these comments have
>since been removed.

The reason might be that i showed (#9644) that his comment is false,
and sqr() is NOT the same as i*i if the operand is an int64 type.

- Asbjørn

John Herbster

unread,
Aug 26, 2005, 10:02:36 PM8/26/05
to

"Lord Crc" <lor...@hotmail.com> wrote
> ... I showed (#9644) that his comment is false, and sqr()

> is NOT the same as i*i if the operand is an int64 type.

Asbjørn,
I think that this area of code generation is a bit of a mess.
That the use of the result is not considered, nor in some
cases the possibility of overflow of the operands during
multiplies and squares seems like a lame decision just
to make the compiler writer's life simpler at the expense
of the users'. I know that it requires a lot of *careful* work
to do a good job in this area. But this is a basic area that
can save a lot of users a lot of pain, if implemented well.
Regards, JohnH

Lord Crc

unread,
Aug 26, 2005, 10:09:12 PM8/26/05
to
On Fri, 26 Aug 2005 21:02:36 -0500, "John Herbster"
<herb-sci1_AT_sbcglobal.net> wrote:

>I think that this area of code generation is a bit of a mess.
>That the use of the result is not considered, nor in some
>cases the possibility of overflow of the operands during
>multiplies and squares seems like a lame decision just
>to make the compiler writer's life simpler at the expense
>of the users'.

Well, I hope they try to make it consider ther types of the operands
first!

However, if multiplication should return int64's, then the other basic
operators should as well (addition, subtraction), imho. I think it
should return int's for int*int or sqr(int), but issue a hint if you
assign it to an int64 or similar.

- Asbjørn

John Herbster

unread,
Aug 27, 2005, 7:17:37 AM8/27/05
to

"Lord Crc" <lor...@hotmail.com> wrote
> However, if multiplication should return int64's, ...

If we program
r := a*b;
where a and b are byte and r is word, I think
for the programmers sake that the multiply
should give a word result without bothering
with error checking. I suggest similar action
for other "safe" operations.

If a, b, and r are LongInt, then some overflow
and range checking should be allowed for,
if the programmer has requested it. If checking
is not requested, then the truncated result or
some result indicated error should be used.
I suggest similar action for other "unsafe"
operations.

For complex expressions the compiler should
analyze, the best that is possible, for the type
of arithmetic to do.

The smart programmer should then be able
to guide this operation with parentheses and
by breaking up this calculation with the use
of intermediate results.

--JohnH

Dr John Stockton

unread,
Aug 28, 2005, 8:00:52 AM8/28/05
to
JRS: In article <43104b1b$1...@newsgroups.borland.com>, dated Sat, 27 Aug
2005 06:17:37, seen in news:borland.public.delphi.language.delphi.genera
l, John Herbster <herb-sci1_AT_sbcglobal.net@?.?> posted :

>
>"Lord Crc" <lor...@hotmail.com> wrote
>> However, if multiplication should return int64's, ...
>
>If we program
> r := a*b;
>where a and b are byte and r is word, I think
>for the programmers sake that the multiply
>should give a word result without bothering
>with error checking. I suggest similar action
>for other "safe" operations.


IIRC, in Pascal & Delphi, the type of an arithmetic operation is the
smallest type into which the types of both operands can fit.

The alternatives are to make it the smallest type into which the answer
must inevitably fit - impossible for the largest type ; or to define the
type of the arithmetic by the type of the variable being assigned to -
which rule fails for Bool := (A+B*C) > 0 ; where there is no such
numeric variable; or to use typed operators, as in C := A longint(*) B .

I suspect the present rule is the most practical universally-applicable
rule; and that in any system of performing arithmetic using only a
finite number of bits but with "mathematical" numbers in mind there must
necessarily be some rules that must be taught, learned, remembered, and
applied.

--
© John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 MIME. ©
<URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/&c., FAQqy topics & links;
<URL:http://www.merlyn.demon.co.uk/clpb-faq.txt> RAH Prins : c.l.p.b mFAQ;
<URL:ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip> Timo Salmi's Turbo Pascal FAQ.

John Herbster

unread,
Aug 28, 2005, 1:03:04 PM8/28/05
to

"Dr John Stockton" <j...@merlyn.demon.co.uk> wrote


> I suspect the present rule is the most practical universally-
> applicable rule; and that in any system of performing arithmetic

> using only a finite number of bits but with "mathematical"
> numbers in mind there must necessarily be some rules
> that must be taught, learned, remembered, and applied.

Dr. John, et. al,
I don't think that the present "rule", if there is one, is
universally followed by the present Delphi compiler. Further,
I suggest, in the interest of producing better code, that if
the programmer requests overflow and range checking, then the
compiler should do all possible checking, in order to notify
the user when his code cannot do his intended arithmetic.
Regards, JohnH

Guenther Wimpassinger

unread,
Aug 29, 2005, 5:12:20 AM8/29/05
to

"John Herbster" <herb-sci1_AT_sbcglobal.net> schrieb

>
> "Guenther Wimpassinger" <gw_...@pickem.at> wrote
>
>> > Further, note that in Delphi's arithmetic, the result of any
>> > two-operand arithmetic multiplication the intermediate
>> > result will be the type of the largest (in size) operand
>
>> Are you sure?
>
>> This is from the Delphi (7) Language Guide (Ch. 5 / Integer Types)
>> from Borland
>> -----------------
>> In general, arithmetic operations on integers return
>> a value of type Integer—which, in its current implementation,
>> is equivalent to the 32-bit Longint. Operations return a
>> value of type Int64 only when performed on one or more
>> Int64 operand.
>> -----------------
>
>> And during the test multiplying two byte variables results in
>> a 32 bit value.
>
> No, I am not sure. The help documentation is not clear in its
> use of integer (vs. signed 32-bit integer). Nor am I sure what
> will happen to the intermediate results of multiplies or the
> sqr() function when the default integer becomes 64 bits.

Do you mean the "online help" with help documentation?

If I would be the compiler writer, I would calculate "native
arithmetic" operations (+, -, *, /, div, mod [see DLG Ch.4
/ Arithmetic Operations]) in the "native cpu" format.
in IA32 -> 32bit, in IA64, x64 -> in 64bit regardless
of the operands size. I think that is the way the compiler
actually generates the code.

I agree that in general sqr should be treated as x*x. But
for sqr there is AFAIK some compiler magic going on.

0 new messages