473,771 Members | 2,347 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Find Greater or Equal

Can someone check this? If it's OK, you can use however you want... :-)
It should search for an element in an array and, if it can't find it, return
the next element.
key is what you are searching, in a *base array of LONG with num elements.
After some tests it seems to work well (the original version was filled with
ASSERTs)
(I will use this function in a bigger look-for-or-insert function)

Some notes:
The function returns the index of the element.
2, 2, 2, 3. Search for 2, it will return the second one (index = 1)
1, 2, 2, 4. Search for 2, it will return the first one (index = 1)
But it should always return the first bigger-than-key element, if it can't
find key (this is very important. I have to insert a new element in that
place, and I want the array to be still ordered after the insertion)
If key > max(all-the-elements) then the function returns -1;

int FindGreaterOrEq ual(LONG key, LONG *base, size_t num)
{
LONG lo = 0;
LONG hi = num - 1;
LONG mid;

size_t half;

if (!num || key > base[hi]) {
return -1;
}

while (lo != hi) {
if (num == 2) {
if (key < base[lo]) {
return lo;
}

return hi;
}

half = num / 2;

mid = lo + ((num & 1) ? half : (half - 1));

if (key == base[mid]) {
return mid;
} else if (key < base[mid]) {
hi = mid;
num = ((num & 1) ? (half + 1) : half);
} else {
lo = mid + 1;
num = half + 1;
}
}

return lo;
}
Nov 14 '05 #1
3 2227
On Fri, 20 Feb 2004, Massimiliano Alberti wrote:
Can someone check this? If it's OK, you can use however you want... :-)
It should search for an element in an array and, if it can't find it, return
the next element.
key is what you are searching, in a *base array of LONG with num elements.
After some tests it seems to work well (the original version was filled with
ASSERTs)
(I will use this function in a bigger look-for-or-insert function)
It is good that you are validating this function before attempting to use
it in another function. Working on parts at a time is always better than
trying to write a program as one big thing. However, validating a function
by testing it is not that great. Empirical testing will catch some bugs
but you really want to test your design/logic.
Some notes:
The function returns the index of the element.
2, 2, 2, 3. Search for 2, it will return the second one (index = 1)
1, 2, 2, 4. Search for 2, it will return the first one (index = 1)
But it should always return the first bigger-than-key element, if it can't
find key (this is very important. I have to insert a new element in that
place, and I want the array to be still ordered after the insertion)
If key > max(all-the-elements) then the function returns -1;
I'm assuming the list of numbers is sorted in non-descending order.
int FindGreaterOrEq ual(LONG key, LONG *base, size_t num)
{
LONG lo = 0;
LONG hi = num - 1;
LONG mid;
size_t half;
Why is half a size_t data type and the others are LONG?
if (!num || key > base[hi]) {
return -1;
}
First case: Key is greater than all elements in the array. Pretty straight
forward.
while (lo != hi) {
if (num == 2) {
if (key < base[lo]) {
return lo;
}
return hi;
}
Second case: There are only 2 elements in the array. There is a mistake
here. Try:

LONG base[] = {2, 4};
LONG key = 2;
half = num / 2;
mid = lo + ((num & 1) ? half : (half - 1));
You might want to put some comments if this is homework. It is pretty
obvious to me what (num & 1) is meant to do here. It is also not
immediately obvious that num==1 will work for this function. Are you
sure the function works if num==1? There are 3 cases to test if num==1.
if (key == base[mid]) {
return mid;
} else if (key < base[mid]) {
hi = mid;
num = ((num & 1) ? (half + 1) : half);
} else {
lo = mid + 1;
num = half + 1;
}
}

return lo;
}


At this point I look at this code and think you could write it a little
more clear. I see at least one bug in it.

--
Send e-mail to: darrell at cs dot toronto dot edu
Don't send e-mail to vi************@ whitehouse.gov
Nov 14 '05 #2
Second try... Fully commented. I have corrected two errors, the key <=
base[lo] and the num = half + 1 that now is a num = half.
I'm using size_t for num and half while using LONG for the index because
this is not the original program... You don't want to see something very
very ugly very very based on pointers :-) It's much more readable if you see
indexes and LONGs. To obtain the real program you have to imagine that LONG
is void* (casted to char* to be used), base[something] is something without
base (where something is a char*), that even key is a char* and that the
simple <, >, = are functions that compare (yes, it's lousily based on the
bsearch function). Quite ugly! :-)
The program is based on the method of bisection. We take the middle element
and then decide which half of the array is the "good" half. We repeat the
process. Sometimes we have to include the middle element in the "good" half,
sometimes not. In the end we will have an array of one or two elements. If
we have only one element the while will die and we will return the index of
the element. If we have two elements then we analyze the first one and then
we decide.

int FindGreaterOrEq ual(LONG key, LONG *base, size_t num)
{
LONG lo = 0; // Index of first element. Note that lo and hi will be
changed as we bisect the array. So will num (the number of elements between
lo and hi), half (half of num) and mid (index of the middle element)
LONG hi = num - 1; // Index of last element
LONG mid; // Index of middle element

size_t half; // half-number of elements (number of lo-mid elements)

if (!num || key > base[hi]) { // if no elements or key > highest element
(last element), return -1
return -1;
}

while (lo != hi) { // if there is a single element then we don't have to
analyze
assert(num == (hi - lo + 1)); // just to be sure
if (num == 2) { // if we have only two elements, then the bisection
method doesn't work
if (key <= base[lo]) { // compare with first element, if key <=
base[lo], then return lo
return lo;
}

return hi; // return hi
}

half = num / 2; // half number of elements

mid = lo + ((num & 1) ? half : (half - 1)); // if num is odd (num &
1), then we will use (half + 1) elements (so we will round half to the next
integer), if even half elements

if (key == base[mid]) { // if the middle element is == key, then
return it's index.
return mid;
} else if (key < base[mid]) { // if the key is lesser than the middle
element, then we bisect on the middle element. We have to include the middle
element because it could be the first element greater-than.
hi = mid;
num = ((num & 1) ? (half + 1) : half); // we recalc the number of
elements of the sub-lists. The first sublist is the
half/half.5-rounded-to-half+1 list
} else {
lo = mid + 1; // the key is greater than the middle element. We
bisect on the middle element. We can exclude the middle element because it
can't be the first greater-than element and we have already compared it with
key
num = half; // we recalc the number of elements of the sub-lists.
The second sublist always has half elements (the odd element is always
included in the first one)
}
}

return lo; // single element case: return the index of the element.
}
Nov 14 '05 #3
Massimiliano Alberti wrote:

[snip - explanation of binary search]
[comments and asserts removed for readability]
int FindGreaterOrEq ual(LONG key, LONG *base, size_t num)
{
LONG lo = 0;
LONG hi = num - 1;
LONG mid;

size_t half; // half-number of elements (number of lo-mid elements)

if (!num || key > base[hi]) {
return -1;
}
This is an optimization. IMO, you don't need this as num==0 is a programmer
error, and key > base[hi] will be caught by the more general expression below.
while (lo != hi) {
if (num == 2) {
if (key <= base[lo]) {
return lo;
}
return hi;
}
half = num / 2;
You don't need to check if num==2, and you don't need to compute half.
mid = lo + ((num & 1) ? half : (half - 1));
This is a terrible expression. Generally speaking, you should not mix arithmetic
and bit-wise operations. In any case, it doesn't matter where your midpoint is
because key will always be in the range (lo,mid) or (mid+1,hi).

if (key == base[mid]) {
return mid;
} else if (key < base[mid]) {
hi = mid;
This should be mid+1. Since you know key is not at mid, there is no reason to
keep mid in the new range.
num = ((num & 1) ? (half + 1) : half);
The algorithm is much simpler if you hold on to num!
} else {
lo = mid + 1;
num = half;
Ditto.
}
}
return lo;
You should always return mid here since the element is either at mid, or
mid==low==0. This is consistent with checking whether key == base[mid].
}


Here is how you might write this without changing num:

int
bsearch_ge(long key, long *base, int num)
{
int l = 0;
int h = num-1;
int m = (l+h)/2;

/* generic binary search */
while(l < h){
if(key == base[m])
return m;
if(key < base[m])
h = m - 1;
else
l = m + 1;
m = (l+h)/2;
}

/* l==h; apply "greater than or equal to" logic */
if(key > base[m]){
if(m < num-1)
return m+1; /* key > base[m] && m < num-1 */
else
return -1; /* key > base[m] && m == num-1 */
}
return m; /* key <= base[m] */
}

/david

--
Andre, a simple peasant, had only one thing on his mind as he crept
along the East wall: 'Andre, creep... Andre, creep... Andre, creep.'
-- unknown
Nov 14 '05 #4

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

Similar topics

9
25163
by: Hebar Tiltwobler | last post by:
I need to figure out if the current date (passed in as a string) is equal to or greater then a field in my database in the format of- M/D/YYYY AND if the date is less then another field in my database. "... WHERE '" & cdate(request("date")) & "' >= CONVERT(varchar, (datePart(M,appointmentStart)/datePart(D,appointmentStart)/datePart(YYYY,app ointmentStart)), 103)) AND "&_ "'" & cdate(request("date")) & "' <= (CONVERT(varchar,...
8
5087
by: Equilibrium | last post by:
what did I wrong with the program ? (use VC++) /* Using if statment, relational operators, and equality operators */ #include<stdio.h> int main() { printf("Enter two integers, and I will tell you\n"); printf("the relationships they satisfy: ");
2
12360
by: Michael | last post by:
Need some help trying to read values from web controls - specifically *finding* the controls (like a drop down list) - that are added dynamically added within an asp:panel control. The page contains multiple panels within the form. The panels appear at different times - for our argument, let's say panel 1 appears first, users clicks a submit button and then panel 1 disappears and panel 2 appears, etc. When clicks on the submit button...
7
2716
by: BobRoyAce | last post by:
Let's say I have a text box on a page in which a user is to enter a monetary amount and that I want to ensure that the user enters a value greater than or equal to a certain value that will be determined by interrogating a database at runtime. There is a button on the page that the user clicks on to Save the data they have entered. In the click event of this button I want to check to see if they have entered a value no greater than the...
0
1552
by: Michael Mallete | last post by:
good day everyone! i am using postgresql-8.0beta2-dev3 windows port, with postgis-0.9 add-on. anyway, while trying to insert a table using shp2pgsql, i get this error: psql:temp.sql:38: ERROR: Unicode characters greater than or equal to 0x10000 are not supported
6
1502
by: wbrowse | last post by:
Wy in Php 01 is greater than 1 ?
22
4727
by: Steve Richter | last post by:
Does the .NET framework provide a class which will find the item in the collection with a key which is closest ( greater than or equal, less than or equal ) to the keys of the collection? ex: collection keys are 20, 30, 40, 50, 60, 70, 80 find key which is >= 35. would return the 30 key.
2
5088
by: kl | last post by:
Hi, I'm trying to learn some STL using map or hash_map would maybe even better to use but I don't really know how to find a specific struct depending on a DWORD value that is in range of two DWORD values (see below for more). So what I trying to achieve is creating a look up table of a IP adress with a start adress (a DWORD value) and a end adress (a DWORD value) which I would like to look up to the get the Country name
15
3592
by: kpfunf | last post by:
I have one table of transactions, another table of price quotes. Transactions are nearly daily; quotes are periodic, roughly once per week. In a query, I want to pull the oldest (or least date) price quote whose date is greater or equal to the transaction date (trying to find the nearest price quote to compare to actual price paid). I have criteria for the price quote date as >=Trans Date, and tried setting the field to min or last, but these...
0
9619
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
10260
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10102
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...
1
10038
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
5354
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5482
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4007
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3609
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2850
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.