473,396 Members | 1,859 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,396 software developers and data experts.

Problem finding key in STL map with gcc 4.1.0

I have 2 Suse Linux PCs which I compile my code on. Until recently
they both had gcc 4.0.X on them, but I upgraded one of them to gcc
4.1.0. I have come across a very strange problem in the following code
which uses an STL map:

void Distribution::AddToDistribution (double& valueToAddToDistribution)
{
int n;
n = static_cast<int>(valueToAddToDistribution/itsBinWidth);

float keyToAddTo;
keyToAddTo = (n + 0.5)*itsBinWidth;

// std::cout << "n: " << n << ", keyToAddTo: " << keyToAddTo <<
std::endl;

std::map<float, int>::iterator addToDistributionIterator;

addToDistributionIterator = itsDistributionValues.find(keyToAddTo);

if (addToDistributionIterator == itsDistributionValues.end()) // Key
not found in map
{
itsDistributionValues[keyToAddTo] = 1;
}

else // Key present in map
{
addToDistributionIterator->second++;
}
}

On one machine with gcc version 4.0.2 20050901 (prerelease) (SUSE
Linux) (AMD 64bit) this works fine and the code goes into the "else //
Key present in map" part of the code as required. However, on the
machine with gcc version 4.1.0 (intel P4) it doesn't - the map key
isn't found - it worked fine with 4.0.X however! The strange thing is
that, if i uncomment the line:

"std::cout << "n: " << n << ", keyToAddTo: " << keyToAddTo <<
std::endl;"

to print the key value to the screen (used as a quick debug/test line),
then the code works fine and enters the "else // Key present in map"
as required.

Do you think that this is a compiler bug, or a bug in my code that the
compiler wasn't sensitive to before?

Any help gratefully received,

Graham

Apr 3 '06 #1
6 2463
gr***************@gmail.com wrote:
I have 2 Suse Linux PCs which I compile my code on. Until recently
they both had gcc 4.0.X on them, but I upgraded one of them to gcc
4.1.0. I have come across a very strange problem in the following code
which uses an STL map:
<snip>
// std::cout << "n: " << n << ", keyToAddTo: " << keyToAddTo <<
std::endl;

std::map<float, int>::iterator addToDistributionIterator;

Have you heard the rule of thumb that it's usually a bad idea to
compare two floating point values for equality? Well using a map keyed
on float values is the same thing. You often get surprised by the way
things are rounded, and the behaviour may vary from compiler to
compiler (or even the order of the mathematical operations you use to
calculate the value).

I would guess that by outputing keyToAddTo via cout, you have taken a
reference to it and thus forced it into memory whereas without that
line it would have remained in a floating point register. Registers
will often have a different precision than the memory location used to
store them, and I think your problems are due to the rounding that
follows.

The ideal solution would be to key the map on an integer type (I'm sure
you can find a way). Failing that, supply a comparator to the map that
will compare floats using a predefined tolerance rather than ==.

Apr 3 '06 #2
Hello,
gr***************@gmail.com wrote:
std::map<float, int>::iterator addToDistributionIterator;

You should learn a fair deal about floating point arithmetics, there are
some papers in the net, and there are books. Use a search engine, and
read, well invested time.

You probably have got trapped in the most simple pitfall, you cannot
rely directly on equality or < or > to compare floating point values
calculated from different source values. Different compilers create
different code, and different values, e.g. if the hardware has excess
precision and intermediate results don't get rounded due to
optimization.

You as a programmer have to decide what ranges of floating point values
are to be treated as one value each, that's the key. Consider the
precision of the input values.

isn't found - it worked fine with 4.0.X however! The strange thing is
that, if i uncomment the line: then the code works fine and enters the "else // Key present in map"
as required.
This is a clear sign for an optimization issue. Printing a value changes
a lot in compilation. Usually a lot of optimization possibilities are
killed, because printing cannot be inlined, i.e. a real function is
called with all its natural overhead and different optimization
opportunities. Compilers are allowed to produce different floating
point results depending on optimization, if the precision is above a
specified minimum. A great deal of the recent changes to gcc, the
compiler in question here, is due to better optimization.

Do you think that this is a compiler bug, or a bug in my code that the
compiler wasn't sensitive to before?


It's the last choice, clearly. It's a bug to rely on maximum precision
of floating point values up to equality. Usually, the input data has
remarkably less precision, anyway.

Bernd

Apr 3 '06 #3
Pete C wrote:
gr***************@gmail.com wrote:
I have 2 Suse Linux PCs which I compile my code on. Until recently
they both had gcc 4.0.X on them, but I upgraded one of them to gcc
4.1.0. I have come across a very strange problem in the following code
which uses an STL map:
std::map<float, int>::iterator addToDistributionIterator;

Have you heard the rule of thumb that it's usually a bad idea to
compare two floating point values for equality? Well using a map keyed
on float values is the same thing. You often get surprised by the way
things are rounded, and the behaviour may vary from compiler to
compiler (or even the order of the mathematical operations you use to
calculate the value).

The ideal solution would be to key the map on an integer type (I'm sure
you can find a way). Failing that, supply a comparator to the map that
will compare floats using a predefined tolerance rather than ==.


In general, that's a good advice. However, map requires operator< or a
similar weak ordering. For floats, it's all too easy to define a
BrokenLess(float,float) such that

BrokenLess(a,b)==false && BrokenLess(b,a)==false &&
BrokenLess(a,c)==false && BrokenLess(c,a)==false &&
BrokenLess(b,c) == true; // BAD!

If a and b are equivalent, and a and c also, then b and c must be
equivalent
as well. Now, with the normal epsilon trick, imagine what happens if
b == a+eps and c == a-eps.

Floats are basically not suited very well, if at all, for maps.

HTH,
Michiel Salters

Apr 3 '06 #4
Thanks very much - I can redesign the class so that the key is an
integer, and I'll bear your advice in mind in future.

Graham

Apr 3 '06 #5
Mi*************@tomtom.com wrote:
In general, that's a good advice. However, map requires operator< or a
similar weak ordering. For floats, it's all too easy to define a
BrokenLess(float,float) such that

BrokenLess(a,b)==false && BrokenLess(b,a)==false &&
BrokenLess(a,c)==false && BrokenLess(c,a)==false &&
BrokenLess(b,c) == true; // BAD!
I'd imagine it's inevitable (rather than merely 'easy'), is it not?
Similarly to how any normal epsilon-based comparison can appear to
yield:

a == b && b == c && a != c

That's just the nature of the game, and why it's so important to choose
the right epsilon for your application (and why it's even more
important to not put yourself in that position in the first place).
Floats are basically not suited very well, if at all, for maps.


agreed...

Apr 3 '06 #6
Pete C wrote:

I'd imagine it's inevitable (rather than merely 'easy'), is it not?
Similarly to how any normal epsilon-based comparison can appear to
yield:

a == b && b == c && a != c

That's just the nature of the game, and why it's so important to choose
the right epsilon for your application (and why it's even more
important to not put yourself in that position in the first place).


The point is that a comparator like this does not meet the requirements
for use in a map (unless epsilon is 0). Typically you'll get runtime
crashes, which only start showing up the night before your product is
supposed to ship.

--

Pete Becker
Roundhouse Consulting, Ltd.
Apr 4 '06 #7

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

Similar topics

8
by: Dave | last post by:
Hi all, I've been trying to figure this out for the last day and a half and it has me stumped. I've got a web application that I wrote that keeps track of trading cards I own, and I'm moving it...
7
by: addled | last post by:
Hi there, after reading posts here for a few months, I've built the courage to see if someone can see where I"m going wrong in the webpage I've been working on. In particular the horizontal nav...
117
by: Peter Olcott | last post by:
www.halting-problem.com
2
by: John Jumper | last post by:
I am using an XmlDataSource in VS2005Beta1 and setting the TransformFile property in my ASCX and it is finding both files. However, the resulting data does not contain any of the sub nodes of the...
4
by: | last post by:
I am stuck in a situation and I do believe that this should work, but it doesn't. I have a unmanaged dll, that uses MFC. This works great. Now I recompile the unmanaged dll so it contains...
6
by: Jared Turley | last post by:
I am currently having an issue with an ASP.NET page not finding the class library located in the application's /bin directory. The page recognizes the compiled .dll class when running on my...
1
by: Doug | last post by:
The html below shows DataList "DiscountList" nested within DataList "EventItemList". DiscountList contains a Label control. I'm trying to find the label, using FindControl, during...
6
by: Florian Lindner | last post by:
Hello, I have these class declarations class CBauteil { private: int m_iNumber; int m_iWeight; public: int getNumber(); void setNumber(int);
1
by: Empyrean | last post by:
I'm attempting to make my first program that involves file input, but I'm running into problems finding the .txt file. I placed the file inside the same folder as the rest of the project, but it...
1
by: avik1612 | last post by:
Hi, I have created a program to find text files in a particular directory or folder. and to find a particular word in that files i finding it difficult to put the list in an array and finding...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
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
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...
0
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,...

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.