Opened 14 years ago

Closed 14 years ago

Last modified 14 years ago

#2228 closed Bugs (invalid)

signed overflow problem in weighted_sum on VC9.0

Reported by: Pavol Droba Owned by: Eric Niebler
Milestone: Boost 1.36.0 Component: accumulator
Version: Boost 1.36.0 Severity: Problem
Keywords: Cc:

Description

Hi,

I have spotted rather unexpected behaviour while using weighted_sum.

Here is the simple code:

// use namespaces
using namespace boost::accumulators;
using namespace std;

// create a int accumulator with std::size_t weight
accumulator_set<int, features<tag::weighted_sum>, std::size_t> Accum;

// Accumulate negative value with positive weight
Accum(-56, boost::accumulators::weight=3);

// Print the output
wcout << "sum: " << boost::accumulators::weighted_sum(Accum) << endl;

I was expecting to get result -168, however I got 4294967128.

I have traced the problem to weighted_sum_impl.

I don't know why, but

weighted_sum_impl<int, unsigned int, tag::sample>::weighted_sample

is resolved to unsigned int. I think this is plain wrong.

Change History (3)

comment:1 by Eric Niebler, 14 years ago

Resolution: invalid
Status: newclosed

This is not a bug. The sample is multiplied by the weight. In C++, and int multiplied by an unsigned int is an unsigned int. (Try it and see.)

If you want the result to be an int, use an int for the weight type.

comment:2 by Pavol Droba, 14 years ago

I understand that the current solution is technically correct. However I think that conceptually it is not.

An example: To calculate a weighted mean of signed integers, where weight represents sample cardinality, I would consider it quite natural to expect that the mean will be signed, since I'm accumulating signed integers. Even though the cardinality is natural (i.e. unsigned) number.

comment:3 by Eric Niebler, 14 years ago

I understand your point, but I still disagree. I'm not going to get into guessing what a "better" type to hold the result is. It can be argued from the other side ... that using an int to hold the result of an (int*unsigned) can overflow and wrap. There is no good solution. Following the rules of C++ is simply the best (as in least surprising, easiest to explain) thing to do.

Note: See TracTickets for help on using tickets.