473,395 Members | 1,452 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

why does STL binary-serach twice when deleting a set member?

JDT
Hi,

The last statement at the end of this post is to delete a set member
7.7. I set a break point inside ltstr::operator(). I found out that
STL binary-seach the set twice. How come? I have another problem that
a member in a set cannot be deleted. I think I may be able to solve
that problem if I can figure out the problem posted here. Thanks for
your help.

The sequence of (f1, f2) STL goes through is (7.7, 4.4), (7.7, 6.6),
(7.7, 8.8), (7.7, 7.7), (4.4, 7.7), (6.6, 7.7), (8.8, 7.7), and finally
(7.7, 7.7) again.
// *****************************
struct ltstr // less than
{
bool operator()(const float f1, const float f2) const
{
return f1 f2;
}
};

int main(int argc, char* argv[])
{

set<float, ltstr s;
s.insert(1.1);
s.insert(2.2);
s.insert(3.3);
s.insert(4.4);
s.insert(5.5);
s.insert(6.6);
s.insert(7.7);
s.insert(8.8);
s.insert(9.9);

s.erase(7.7);
....

JD
Oct 19 '06 #1
8 1842
JDT <jd*******@yahoo.comwrote:
The last statement at the end of this post is to delete a set member
7.7. I set a break point inside ltstr::operator(). I found out that
STL binary-seach the set twice. How come?
This is probably just an implementation detail, but from what I
understand many implementations of std::set internall use some sort of
tree structure to keep the set sorted. When you delete a member, the
first search is probably to find the element to be deleted, and the
second may be some sort of rebalancing of the tree.
I have another problem that
a member in a set cannot be deleted. I think I may be able to solve
that problem if I can figure out the problem posted here. Thanks for
your help.
This problem may be a consequence of the fact that floating point
arithmetic is not exact; see

http://www.parashift.com/c++-faq-lit...html#faq-29.17

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Oct 19 '06 #2
JDT
Hi Marcus,

Thanks for the explanation. But an element cannot be deleted even after
I pay attention to your 2nd point. Basically I feed the following
customized less-than operator into a set. (I hope that the fTolerance
can be as small as possible) One in thousands of elements cannot be
deleted. I think the operator is only used for sorting/searching, but
not for the final matching. To match an element to be deleted at the
end of searching, pointers to CSetMember will be used for comparison.
Am I right? The operator shouldn't cause this type of problem as long
as it always returns a consistent bool value. It really puzzles me ....

struct lt
{
bool operator() (const CSetMember *s1, const CSetMember *s2) const
{
float f1 = s1->a * s1->b / s1->c;
float f2 = s2->a * s2->b / s2->c;
if (abs(f1-f2) fTolerance)
return f1 < f2;
else
return s1->id < s2->id; // id is a unique integer
}
};

JD
Marcus Kwok wrote:
JDT <jd*******@yahoo.comwrote:
>>The last statement at the end of this post is to delete a set member
7.7. I set a break point inside ltstr::operator(). I found out that
STL binary-seach the set twice. How come?


This is probably just an implementation detail, but from what I
understand many implementations of std::set internall use some sort of
tree structure to keep the set sorted. When you delete a member, the
first search is probably to find the element to be deleted, and the
second may be some sort of rebalancing of the tree.

> I have another problem that
a member in a set cannot be deleted. I think I may be able to solve
that problem if I can figure out the problem posted here. Thanks for
your help.


This problem may be a consequence of the fact that floating point
arithmetic is not exact; see

http://www.parashift.com/c++-faq-lit...html#faq-29.17
Oct 19 '06 #3
"JDT" <jd*******@yahoo.comwrote in message
news:jk******************@newssvr13.news.prodigy.c om...
Thanks for the explanation. But an element cannot be deleted even after I
pay attention to your 2nd point. Basically I feed the following
customized less-than operator into a set. (I hope that the fTolerance can
be as small as possible) One in thousands of elements cannot be deleted.
I think the operator is only used for sorting/searching, but not for the
final matching. To match an element to be deleted at the end of
searching, pointers to CSetMember will be used for comparison. Am I right?
The operator shouldn't cause this type of problem as long as it always
returns a consistent bool value. It really puzzles me ....

struct lt
{
bool operator() (const CSetMember *s1, const CSetMember *s2) const
{
float f1 = s1->a * s1->b / s1->c;
float f2 = s2->a * s2->b / s2->c;
if (abs(f1-f2) fTolerance)
return f1 < f2;
else
return s1->id < s2->id; // id is a unique integer
}
};
If this function ever returs true for both lt(s1, s2) and lt(s2, s1)
(and I strongly suspect it does) then it is *not* a strict weak
ordering, and set will not behave properly.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Oct 19 '06 #4
JDT
Hi P.J.,

Since I didn't change both s1's and s2's a, b, c, and id, the same
machine and same compile will always produce the same values of f1 and
f2. It's a strict weak ordering unless "(abs(f1-f2) fTolerance)"
produces different bools for lt(s1, s2) and lt(s2, s1). Is it possible?

JD
P.J. Plauger wrote:
"JDT" <jd*******@yahoo.comwrote in message
news:jk******************@newssvr13.news.prodigy.c om...

>>Thanks for the explanation. But an element cannot be deleted even after I
pay attention to your 2nd point. Basically I feed the following
customized less-than operator into a set. (I hope that the fTolerance can
be as small as possible) One in thousands of elements cannot be deleted.
I think the operator is only used for sorting/searching, but not for the
final matching. To match an element to be deleted at the end of
searching, pointers to CSetMember will be used for comparison. Am I right?
The operator shouldn't cause this type of problem as long as it always
returns a consistent bool value. It really puzzles me ....

struct lt
{
bool operator() (const CSetMember *s1, const CSetMember *s2) const
{
float f1 = s1->a * s1->b / s1->c;
float f2 = s2->a * s2->b / s2->c;
if (abs(f1-f2) fTolerance)
return f1 < f2;
else
return s1->id < s2->id; // id is a unique integer
}
};


If this function ever returs true for both lt(s1, s2) and lt(s2, s1)
(and I strongly suspect it does) then it is *not* a strict weak
ordering, and set will not behave properly.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com

Oct 19 '06 #5
"JDT" <jd*******@yahoo.comwrote in message
news:d5******************@newssvr27.news.prodigy.n et...
Hi P.J.,

Since I didn't change both s1's and s2's a, b, c, and id, the same machine
and same compile will always produce the same values of f1 and f2. It's a
strict weak ordering unless "(abs(f1-f2) fTolerance)" produces different
bools for lt(s1, s2) and lt(s2, s1). Is it possible?
A strict weak ordering unless... is not a strict weak ordering.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Oct 20 '06 #6
"JDT" <jd*******@yahoo.comwrote in message
news:d5******************@newssvr27.news.prodigy.n et...
Hi P.J.,

Since I didn't change both s1's and s2's a, b, c, and id, the same machine
and same compile will always produce the same values of f1 and f2. It's a
strict weak ordering unless "(abs(f1-f2) fTolerance)" produces different
bools for lt(s1, s2) and lt(s2, s1). Is it possible?
A strict weak ordering unless... is not a strict weak ordering.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com

Oct 20 '06 #7
Hello,

P.J. Plauger wrote:
"JDT" <jd*******@yahoo.comwrote in message
news:jk******************@newssvr13.news.prodigy.c om...
>Thanks for the explanation. But an element cannot be deleted even
after I
pay attention to your 2nd point. Basically I feed the following
customized less-than operator into a set. (I hope that the
fTolerance can
be as small as possible) One in thousands of elements cannot be
deleted. I think the operator is only used for sorting/searching, but
not for the
final matching. To match an element to be deleted at the end of
searching, pointers to CSetMember will be used for comparison. Am I
right? The operator shouldn't cause this type of problem as long as
it always
returns a consistent bool value. It really puzzles me ....

struct lt
{
bool operator() (const CSetMember *s1, const CSetMember *s2) const
{
float f1 = s1->a * s1->b / s1->c;
float f2 = s2->a * s2->b / s2->c;
if (abs(f1-f2) fTolerance)
return f1 < f2;
else
return s1->id < s2->id; // id is a unique integer
}
};

If this function ever returs true for both lt(s1, s2) and lt(s2, s1)
(and I strongly suspect it does) then it is *not* a strict weak
ordering, and set will not behave properly.
Even worse. It's not symmetry, that is causing the biggest problems with
that functor, but transitivity.

Take 3 objects of type CSetMember c1, c2, c3, where ->a and ->c are 1.0
and c1->b == 0.25*fTolerance c2->b == fTolerance c3->b ==
1.75*fTolerance. Then let c1->id==3, c2->id==2 and c3->id==1.

Then we have lt(c1,c2)==false, lt(c2,c1)== true, lt(c2,c3)==false,
lt(c3,c2)== true, so by transitivity lt(c3,c1) should be true, but
lt(c3,c1) == false and lt(c1,c3)==true. This cannot work in general.

If you want to study the effects of a wrong ordering functor on
std::set, you could for example check the order of the elements after
each insert or erase, but not only the neighbouring elements, try all
kinds of distances between the indexes.

Another problem above is using the absolute error to decide. This made
it really easy to find a counterexample. A better way to compare, if
floating point es involved, is comparing values rounded to the accuracy
the input suggests. Imagine a round(d,n) function rounding d to n
digits after decimal point.

// f1, f2 as above
float c1 = round(f1,4);
float c2 = rounf(f2,4);

if (c1 < c2) return true;
if (c1 == c2) return s1->id < s2->id;
return false;

The OP version cuts the range of numbers into pieces of length
fTolerance, but the points, where the pieces end are different with
every starting point. This must not happen. The discretization should
be uniform over all inputs. If you round your input in a sensible
manner, then you might be able to leave out the rounding inside.

Quite some years ago, I had problems with the qsort function of the
standard C library. It crashed, because it was optimized in a way that
a comparision function, not representing an order as required, would
make it including elements outside the array when sorting. A thrilling
experience.

Bernd Strieder

Oct 20 '06 #8
JDT wrote:
Hi,

The last statement at the end of this post is to delete a set member
7.7. I set a break point inside ltstr::operator(). I found out that
STL binary-seach the set twice. How come?
This is apparently not uncommon. Certain implementations will perform
an erase( key) by first calling lower_bound( key) and upper_bound( key),
and then removing the range of iterators returned by these two calls.
Seems wasteful, but typically set, multiset, map, and multimap are built
upon the same underlying framework, usually a red black tree. The range
search then works for all of these containers although it's less than
optimal for the non multi- versions.

FWIW, my version of gcc which seems to be based upon HP and SGI
implementations, does this. To get around this, you can perform a find
operation to return an iterator, and then erase the iterator directly.
If you feel like being fancy, you could even write a templatized
function to do this automatically-- cf. below.

Mark

// nb. untested code!

/* Erases element k, if present, from set s. Returns the number of
* erased elements (0 or 1).
*/
template< typename SetType, typename KeyType>
int setErase( SetType& s, const KeyType& k)
{
typename SetType::iterator it = s.find( k);
if( it == s.end())
return 0;
s.erase( it);
return 1;
}
Oct 20 '06 #9

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

Similar topics

2
by: Valentina | last post by:
What does this C++ line mean? bool bBoolean = (0!=(nInteger&0x08)); I don't understand the nInteger&0x08 bit. Thanks, Valentina
10
by: Fredrik Celin | last post by:
I use IE 6.0 and does some calculations in a javascript. If I run this code: alert(1.4 - 0.5); i get the result 0.8999999999 and not 0.9 Does anybody know why? Is this a bug in IE or...
2
by: greatbooksclassics | last post by:
Open Source DRM? What does everyone think about it? Will Open Source DRM ever catch up to MS DRM? Will DRM ever be integrated into common LAMP applications?...
9
by: Ching-Lung | last post by:
Hi all, I try to create a tool to check the delta (diff) of 2 binaries and create the delta binary. I use binary formatter (serialization) to create the delta binary. It works fine but the...
1
by: ATS | last post by:
PRB - HttpWebRequest does not work with CGI websites and/or RAW data Please help, I'm trying to make a web deploying UserControl that gets RAW binary data that is dynamically created from a...
3
by: Robin Tucker | last post by:
Does anyone have a VB.NET IPersistStream COM interface description I can cadge please? If I remember rightly, you have to "flatten" inherited COM interfaces (I think IPersistStream derives from...
29
by: Vol | last post by:
I think 'atan' can get the angle but it is not the four quadrant angle. Is there any function that i can get the angle from -pi to pi? or I have to use some if ... else? I know in Matlab, we use...
9
by: Someonekicked | last post by:
In my program, I need to open multiple files, and I wont know till after the program execution how many of them (user will enter that value). So I am using a vector of fstream. I am using fstream...
130
by: Daniel Manes | last post by:
I'm baffled. I have a column in a SQL Server Express database called "Longitude," which is a float. When I view the table in a DataGridView, some of the numbers, which only have two decimal places...
9
by: Ed Leafe | last post by:
On Apr 21, 2008, at 1:05 PM, Daniel Fetchinson wrote: Don't most binary distributions include SQLite itself? I installed 2.5.2 on a new WinXP VM, and SQLite is working fine. -- Ed Leafe
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
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,...
0
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...
0
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...
0
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...

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.