473,796 Members | 2,864 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Compare two multiples which could overflow

I have three values:

UInt64 a, b, c, d;

I need to determine if: (a*b) <=(c*d). Naturally, just doing the
multiplication and comparing would tell me the result. However, the
values could potentially overflow. For example, if:

a = UInt64.MaxValue ;
b = 2;
c = UInt64.MaxValue / 3;
d = 4;

I still need to be able to conclude ab cd. I can determine if
wrapping will occur on multiplication by doing:

if (a <= 1 || b <= 1)
{
return false;
}

return ((UInt64.MaxVal ue / a) < b);

But it still doesn't help me determine ab cd. Anybody have any
thoughts on how I could determine this? Thanks.
Oct 3 '08 #1
10 1524
On Fri, 03 Oct 2008 16:35:06 -0700, <ag*******@gmai l.comwrote:
I have three values:

UInt64 a, b, c, d;

I need to determine if: (a*b) <=(c*d). [...]
I'm not aware of anything built into .NET that would do this directly
while handling overflow. If you were dealing with signed 64-bit values,
you could have used the Math.DivRem(), comparing a/c against d/b
(including remainder). But with unsigned 64-bit values, I think you might
as well just do the math the long way.

Pete
Oct 4 '08 #2
ag*******@gmail .com wrote:
I have three values:

UInt64 a, b, c, d;

I need to determine if: (a*b) <=(c*d). Naturally, just doing the
multiplication and comparing would tell me the result. However, the
values could potentially overflow. For example, if:

a = UInt64.MaxValue ;
b = 2;
c = UInt64.MaxValue / 3;
d = 4;

I still need to be able to conclude ab cd. I can determine if
wrapping will occur on multiplication by doing:

if (a <= 1 || b <= 1)
{
return false;
}

return ((UInt64.MaxVal ue / a) < b);

But it still doesn't help me determine ab cd. Anybody have any
thoughts on how I could determine this? Thanks.
Well, you want to split them up a bit, into 32 bit chunks, and check
these. First some theory. Say, n = 2^32, then

a = a0 + a1*n
b = b0 + a2*n
c = c0 + c1*n
d = d0 + d1*n

(a0 + a1*n)*(b0 + b1*n) - (c0 + c1*n)*(d0 + d1*n) 0

a0*b0 + a0*b1*n + a1*b0*n + a1*b1*n*n >
c0*d0 + c0*d1*n + c1*d0*n + c1*d1*n^2 0

a0*b0 + (a0*b1 + a1*b0)*n + a1*b1*n*n >
c0*d0 + (c0*d1 + C1*d0)*n + c1*d1*n*n

Now you do how you always compare numbers, like 321 175. You first
compare the highest digits. If they are not equal, you have your
answer. If they are equal, you compare the second digits, and so on,
and so forth.

Here you do the same. if a1*b1 c1*d1, then the result is true. If
a1*b1 < c1*d1, then the result is false. And if both are equal, you
turn to comparing the next "digit", i.e. you compare
a0*b1 + a1*b0 with c0*d1 + c1*d0, etc.etc.
UInt64 a0 = a & 0xFFFFFFFF;
UInt64 a1 = a >32;
UInt64 b0 = b & 0xFFFFFFFF;
UInt64 b1 = b >32;
UInt64 c0 = c & 0xFFFFFFFF;
UInt64 c1 = c >32;
UInt64 d0 = d & 0xFFFFFFFF;
UInt64 d1 = d >32;

UInt64 x00 = a0*b0;
UInt64 x01 = c0*d0;
// this one may overflow, so split them up even more:
int x10 = (a0*b1) & 1 + (a1*b0) & 1; // lower bit
int x11 = (c0*d1) & 1 + (c1*d0) & 1; // lower bit
UInt64 x20 = a0*b1/2 + a1*b0/2; // top 63 bits
UInt64 x21 = c0*d1/2 + c1*d0/2; // top 63 bits
if (x10 = 2)
{
x20++;
x10 = 0;
}
if (x11 = 2)
{
x21++;
x11 = 0;
}
Byte x20 =
UInt64 x30 = a1*b1;
UInt64 x31 = c1*d1;

Now if the higher parts are compared, the lower bits don't matter,
except if the higher parts are equal. So you can do:

if (x30 x31)
return true;
else if (x30 < x31)
return false;
else if (x20 x21)
return true;
else if (x20 < x21)
return false;
else if (x10 x11)
return true;
else if (x10 < x11)
return false;
else if (x00 x01)
return true;
else
return false;

FWIW, this will not overflow. Each part, x00 - x31, is in the UInt64
range.

--
Rudy Velthuis http://rvelthuis.de

"The whole problem with the world is that fools and fanatics are
always so certain of themselves, but wiser people so full of
doubts." -- Bertrand Russell
Oct 4 '08 #3
Very helpful and informative. Thanks, Rudy.

SteveT
Oct 4 '08 #4
Thanks Rudy. However, I am having difficulty understanding one part of.
Particularly:

int x10 = (a0*b1) & 1 + (a1*b0) & 1; // lower bit
int x11 = (c0*d1) & 1 + (c1*d0) & 1; // lower bit
UInt64 x20 = a0*b1/2 + a1*b0/2; // top 63 bits
UInt64 x21 = c0*d1/2 + c1*d0/2; // top 63 bits

Shouldn't a1, b1, c1, and d1 here all be multiplied by n? After all as you
have your theory above:

a = a0 + a1*n
b = b0 + a2*n
c = c0 + c1*n
d = d0 + d1*n

I guess I don't understand how the n was able to be taken out.

(a0*b1*n) & 1 + (a1*n*b0) & 1;

Because in your code what you are actually doing is:

(a0*(b >32)) & 1 + ((a >32)*b0) & 1;

And I don't see how that is helpful since doing those shifts creates some
arbitrary numbers. I mean, if you have two numbers, a and b, and you split
the numbers in binary half (aHigh, aLow, bHigh, and bLow)... you are saying:

aLow*bHigh + aHigh*bLow

And I am not sure what that is supposed to give us.

That said, in my preliminary tests it seems your code works. But I would
like to understand the logic behind it... could you expand on it a little?

Thanks


"Rudy Velthuis" wrote:
ag*******@gmail .com wrote:
I have three values:

UInt64 a, b, c, d;

I need to determine if: (a*b) <=(c*d). Naturally, just doing the
multiplication and comparing would tell me the result. However, the
values could potentially overflow. For example, if:

a = UInt64.MaxValue ;
b = 2;
c = UInt64.MaxValue / 3;
d = 4;

I still need to be able to conclude ab cd. I can determine if
wrapping will occur on multiplication by doing:

if (a <= 1 || b <= 1)
{
return false;
}

return ((UInt64.MaxVal ue / a) < b);

But it still doesn't help me determine ab cd. Anybody have any
thoughts on how I could determine this? Thanks.

Well, you want to split them up a bit, into 32 bit chunks, and check
these. First some theory. Say, n = 2^32, then

a = a0 + a1*n
b = b0 + a2*n
c = c0 + c1*n
d = d0 + d1*n

(a0 + a1*n)*(b0 + b1*n) - (c0 + c1*n)*(d0 + d1*n) 0

a0*b0 + a0*b1*n + a1*b0*n + a1*b1*n*n >
c0*d0 + c0*d1*n + c1*d0*n + c1*d1*n^2 0

a0*b0 + (a0*b1 + a1*b0)*n + a1*b1*n*n >
c0*d0 + (c0*d1 + C1*d0)*n + c1*d1*n*n

Now you do how you always compare numbers, like 321 175. You first
compare the highest digits. If they are not equal, you have your
answer. If they are equal, you compare the second digits, and so on,
and so forth.

Here you do the same. if a1*b1 c1*d1, then the result is true. If
a1*b1 < c1*d1, then the result is false. And if both are equal, you
turn to comparing the next "digit", i.e. you compare
a0*b1 + a1*b0 with c0*d1 + c1*d0, etc.etc.
UInt64 a0 = a & 0xFFFFFFFF;
UInt64 a1 = a >32;
UInt64 b0 = b & 0xFFFFFFFF;
UInt64 b1 = b >32;
UInt64 c0 = c & 0xFFFFFFFF;
UInt64 c1 = c >32;
UInt64 d0 = d & 0xFFFFFFFF;
UInt64 d1 = d >32;

UInt64 x00 = a0*b0;
UInt64 x01 = c0*d0;
// this one may overflow, so split them up even more:
int x10 = (a0*b1) & 1 + (a1*b0) & 1; // lower bit
int x11 = (c0*d1) & 1 + (c1*d0) & 1; // lower bit
UInt64 x20 = a0*b1/2 + a1*b0/2; // top 63 bits
UInt64 x21 = c0*d1/2 + c1*d0/2; // top 63 bits
if (x10 = 2)
{
x20++;
x10 = 0;
}
if (x11 = 2)
{
x21++;
x11 = 0;
}
Byte x20 =
UInt64 x30 = a1*b1;
UInt64 x31 = c1*d1;

Now if the higher parts are compared, the lower bits don't matter,
except if the higher parts are equal. So you can do:

if (x30 x31)
return true;
else if (x30 < x31)
return false;
else if (x20 x21)
return true;
else if (x20 < x21)
return false;
else if (x10 x11)
return true;
else if (x10 < x11)
return false;
else if (x00 x01)
return true;
else
return false;

FWIW, this will not overflow. Each part, x00 - x31, is in the UInt64
range.

--
Rudy Velthuis http://rvelthuis.de

"The whole problem with the world is that fools and fanatics are
always so certain of themselves, but wiser people so full of
doubts." -- Bertrand Russell
Oct 4 '08 #5
Agendum wrote:
Thanks Rudy. However, I am having difficulty understanding one part
of. Particularly:

int x10 = (a0*b1) & 1 + (a1*b0) & 1; // lower bit
int x11 = (c0*d1) & 1 + (c1*d0) & 1; // lower bit
UInt64 x20 = a0*b1/2 + a1*b0/2; // top 63 bits
UInt64 x21 = c0*d1/2 + c1*d0/2; // top 63 bits

Shouldn't a1, b1, c1, and d1 here all be multiplied by n? After all
as you have your theory above:

a = a0 + a1*n
b = b0 + a2*n
c = c0 + c1*n
d = d0 + d1*n

I guess I don't understand how the n was able to be taken out.
Very simple. They are like numbers in base n instead of base 10. Say
the first number is u + v*n + w*n*n and the other one is x + y*n +
z*n*n. First we must compare w*n*n with z*n*n. But, if w*n*n z*n*n,
then w z, so we only have to compare w and z, and we can skip the n*n
on both sides (since n*n is positive). If they are equal, we must
compare v and y, and if they are equal too, we compare u and x. Of
course this only works because all factors (u, v, w, x, y, z) < n(*)

I had to do the little thing with the one bit since a0*b1 can't
overflow, and a1*b0 can't overflow either, but their sum can. So I took
out the low bits, and divided the rest by 2. IOW,
a0*b1/2 + a1*b0/2 can't overflow anymore, and neither can
a0*b1/2 + a1*b0/2 + 1.

(*) all numbers a0, a1, b0, b1 etc. are max. 0xFFFF, so their product
is a maximum of 0xFFFE0001, IOW always smaller than 2^32.
--
Rudy Velthuis http://rvelthuis.de

"Democracy is where you can say what you think even if you don't
think."
Oct 4 '08 #6
Agendum wrote:
Thanks Rudy. However, I am having difficulty understanding one part
of. Particularly:

int x10 = (a0*b1) & 1 + (a1*b0) & 1; // lower bit
int x11 = (c0*d1) & 1 + (c1*d0) & 1; // lower bit
UInt64 x20 = a0*b1/2 + a1*b0/2; // top 63 bits
UInt64 x21 = c0*d1/2 + c1*d0/2; // top 63 bits

Shouldn't a1, b1, c1, and d1 here all be multiplied by n? After all
as you have your theory above:

a = a0 + a1*n
b = b0 + a2*n
c = c0 + c1*n
d = d0 + d1*n

I guess I don't understand how the n was able to be taken out.

(a0*b1*n) & 1 + (a1*n*b0) & 1;

Because in your code what you are actually doing is:

(a0*(b >32)) & 1 + ((a >32)*b0) & 1;

And I don't see how that is helpful since doing those shifts creates
some arbitrary numbers.
No, they don't. A 64 bit number is generally stored in 2 32-bit dwords.
shifting a 64 bit number to the right by 32 bits leaves you with the
top dword. Comparing 64 bit numbers can first be done on the top
dwords, and then, if inconclusive (if both are the same), on the lower
ones. I use the same principle, but for a few dwords more, since you
have a maximum of 128 bits.

Say, you have the number hex 0x123456789ABCD EF0. Shifting that by 32 to
the right produces 0x12345678.

I must do the bit twiddling because the sum of a0*b1 and a1*b0 can
overflow, but a0*b1/2 + a1*b0/2 can't. This leaves however the lowest
bit unconsidered, so I take them out first, and compare them.

Addition and comparison can be done in every level: byte level, dword
level, bit level, as long as you are sure to do the addition correctly
and ad any carry bits to the next higher part.

Trust me, this is safe and sound, although I devised it on the spot and
actually tried it out in a Delphi console program first. <g>

Delphi has range checks and overflow checks built in, and can be told
to produce an error if they occur. The results are also safe. This is
how low level electronics add and compare: bit by bit. Computers add or
compare byte by byte (8 bit computers), word by word (16 bit computers)
or dword by dword (32 bit computers). How you split them up is not
really important, as long as you take care of the carry bit(s).
--
Rudy Velthuis http://rvelthuis.de

"If everything seems under control, you're just not going fast
enough." -- Mario Andretti
Oct 4 '08 #7
Hi Rudy

Nice to see you around. I see you are still using amusing random quotes in
your signature too :-)

--
Pete
====
http://mrpmorris.blogspot.com
http://www.capableobjects.com

Oct 4 '08 #8
Peter Morris wrote:
Hi Rudy

Nice to see you around. I see you are still using amusing random
quotes in your signature too :-)
I'm still using the same newsreader, XanaNews (the best there is).

I have been reading from and writing to this group before, though.
--
Rudy Velthuis http://rvelthuis.de

"Cole's Law: Thinly sliced cabbage."
Oct 4 '08 #9
On Oct 4, 6:53*am, "Rudy Velthuis" <newsgro...@rve lthuis.dewrote:
Very simple. They are like numbers in base n instead of base 10. Say
the first number is u + v*n + w*n*n and the other one is x + y*n +
z*n*n. First we must compare w*n*n with z*n*n. But, if w*n*n z*n*n,
then w z, so we only have to compare w and z, and we can skip the n*n
on both sides (since n*n is positive). If they are equal, we must
compare v and y, and if they are equal too, we compare u and x. Of
course this only works because all factors (u, v, w, x, y, z) < n(*)
Hey Rudy,

Thanks for explaining. I studied this quite a bit, and I am pretty
sure I understand the approach you are taking here. Basically, how I
evaluated it is:

a*d <=c*b
is
(aL+aH*n)*(dL+d H*n) <=(cL+cH*n)*(bL +bH*n)
is
(aL*dL)+(aL*dH* n)+(aH*n*dL)+(a H*n*dH*n) <=(cL*bL)+(cL*b H*n)+(cH*n*bL)
+(cH*n*bH*n)

Break each side into three pieces:

1) High product: aH*dH <=cH*bH
2) Medium product: aL*dH+aH*dL <=cL*bH+cH*bL
3) Low product: aL*dL <=cL*bL

On the medium product, n was elimated simply by dividing each side by
n:

((aL*dH*n)+(aH* n*dL))/n <=((cL*bH*n)+(c H*n*bL))/n

That is how we get: aL*dH+aH*dL <=cL*dH+cH*dL

I think the only question I have left is regarding your bitshifting.
I understand why you are bitshifting (in the worst case scenario, the
sum of each medium product could overflow). However, I don't
understand why are are adding the bits and only checking for 2. For
example, you have:

int x10 = (a0*b1) & 1 + (a1*b0) & 1; // lower bit
int x11 = (c0*d1) & 1 + (c1*d0) & 1; // lower bit
UInt64 x20 = a0*b1/2 + a1*b0/2; // top 63 bits
UInt64 x21 = c0*d1/2 + c1*d0/2; // top 63 bits
if (x10 = 2)
{
x20++;
x10 = 0;
}
if (x11 = 2)
{
x21++;
x11 = 0;
}

I think the reason you are only checking for two is because it takes 2
half-bits to get one. However, doesn't this mean it is potentially
possible the medium products on one side could be 6 (0110) and 7
(0111), and then the other side 6 (0110) and 6 (0110) and the
comparison test will show they are equal when in fact 7 6... but the
bit for the 7 was lost?

Instead of checking for 2, why not add the bits onto the sum of the
divided numbers regardless of the number of bits?

int x10 = (a0*b1) & 1 + (a1*b0) & 1; // lower bit
int x11 = (c0*d1) & 1 + (c1*d0) & 1; // lower bit
UInt64 x20 = (a0*b1/2 + a1*b0/2) + x10; // top 63 bits
UInt64 x21 = (c0*d1/2 + c1*d0/2) + x11; // top 63 bits

And then skip the x10 and x11 tests entirely?

Thanks
Oct 7 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

37
25372
by: Claude Gagnon | last post by:
Hi, How can we compare sign of numbers in C++ ? Bye, Claude
2
2919
by: david | last post by:
hi: The file can be PDF or Word format. Any help? thx
14
15558
by: purifier | last post by:
Hi everyone, I thought of writing a program which finds the greater of two numbers.. of course with a small condition... without using "if" and conditional operators... I got an idea on how to implement the program... I have an alternative too... that is to use bitwise comparison in the folowing manner: Accept the input Subtract one number from the other Check for the MSB(Most Significant Bit) in the result... See if the result is...
122
5348
by: Einar | last post by:
Hi, I wonder if there is a nice bit twiddling hack to compare a large number of variables? If you first store them in an array, you can do: for (i = 0; i < n; i++) { if (array != value) { /* array differs from value, do something*/
49
14914
by: raju | last post by:
hi can we compare two integers without using relational operators (== != < <= > >=) thanks rajesh s
3
1637
by: Stiemied | last post by:
Working on a Access query to pay multiples of 2 hours of time worked by 75. My problem is I'm not sure how to exclude or remove time that is not a multiple of 2 (round up or down any decimal to nearest whole number). Any help would be greatly appreciated. (/120)*75
1
1429
Wiccadwitch
by: Wiccadwitch | last post by:
Could someone please help??? I'm using paypal's shopping cart which allows for 2 options (such as colors or sizes). I need up to six options with 40 or so colors to choose from. I tried adding 6 but in paypal.com cart it only displays #'s 1 and 6. 2-5 get cut out. Paypal tech gave a website of www.members.aol.com/paypalhelper and said to create select multiples. I did this but there's still something wrong with my code. I can select...
5
1283
by: Patrick A | last post by:
All, I need a little help understanding which concepts / functions / methods / strategies I should use to accomplish what I'll describe below. Note - the real implementation isn't about music - I just thought it would be easier to understand, if not more fun to think about. I have a table with 8,000 rows. Let's call that the "TBL_Fav_Songs" table. It contains a list of my favorite songs, in the column |
3
1915
by: stateemk | last post by:
Hi, I'm probably making this much harder than it needs to be, but I just can't think of how to do this. Each year, a database is created with all employees on it. I need to pull all the employees from the last five years and delete any duplicates. Each table has the exact same fields. So basically, I'm trying to combine tables from 2005, 2006, 2007, 2008 and 2009. Most of the employees will stay the same from year to year, so by combining...
0
9679
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9527
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10223
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
10003
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9050
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7546
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6785
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
2
3730
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2924
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.