I've been working on some simple code for creating histograms and found that following code:
double value = 1.2;
double bucketSize = 0.4;
double bucketId = value / bucketSize;
std::cout << "bucketId as double: " << bucketId << std::endl;
std::cout << "bucketId as int: " << int(bucketId) << std::endl;
results in crazy output of:
bucketId as double: 3
bucketId as int: 2
which basically ruins my trust in computers ;) when looking for the right bucketId
for the value
while creating a histogram.
I know that there are rounding errors etc. but is there any general solution to that problem?
(Just in case) Please don't suggest adding 0.5
to result of the division before casting to int
as apparently it doesn't work very well in some cases (e.g. double value = 3; double bucketSize = 2;
)
Thanks in advance.
I'm basing this more or less on some of your comments to others.
To get the integer part, the solution is to use modf
. But the
integer part of 1.2 / 0.4
could very well be 2
, and not 3
;
0.4
isn't representable in machine floating point (most of
them, at least), so you're dividing by something very close to
0.4
.
The real question is what you actually want. If you're looking
to discretionize (does such a word exist) depending on
bucketSize
, then the correct way of doing this is to use
scaled integers all around:
int value = 12;
int bucketSize = 4;
int bucketId = value / bucketSize;
and then:
std::cout << "bucketId as double: " << bucketId / 10.0 << std::endl;
std::cout << "bucketId as int: " << bucketId / 10 << std::endl;
Otherwise, if you want to keep the values as double, you will
have to decide how close is close for the conversion to int
,
then use your own function:
int
asInt( double d )
{
double results;
double frac = modf( d, &results );
if ( frac > 1.0 - yourEpsilonHere ) {
results += 1.0;
}
return results;
}
It's up to you to decide what value is appropriate for
yourEpsilonHere
; it depends on the application. (The one time
I used this techique, we used 1E-9
. That doesn't mean that
it's appropriate for you, however.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With