The Vee
The Vee

Reputation: 11570

Weird error in unsigned long*double multiplication

I am completely confused by this error that keeps happening in my program, here's an excerpt of a gdb session with the relevant piece of code (blank lines and omissions mine):

(gdb) list
81    Candidate& rankSelect() {
82      float x = (std::uniform_real_distribution<float>(0, 1))(Context::rng);
83      /*debug*/ auto sz = pop.size();
84      /*debug*/ float a = -(float)sz*log(1 - x + x*exp(-1));
85      /*debug*/ float b = -sz*log(1 - x + x*exp(-1));
86      return pop[-(float)pop.size()*log(1 - x + x*exp(-1))];
87    }
88  
...

(gdb) frame
...
86      return pop[-(float)pop.size()*log(1 - x + x*exp(-1))];

(gdb) print sz
$1 = 500

(gdb) ptype sz
type = unsigned long

(gdb) print a
$2 = 54,559597

(gdb) print b
$3 = -2,0128938e+18

As can be seen, I had to add an explicit conversion of pop.size(), which is just a small integer (of type size_type aka unsigned long as pop is a vector<>), otherwise the result to be used as an index is an utter nonsense and caused a segment violation. All the other values are quite well-behaved, the logarithm is guaranteed to be between 0 and -1. Yet -500 times it is suddenly several negative quintillions?!

More strangely, I haven't been able to isolate a MWE. Statements like 500*log(whatever), (size_t)500*log(whatever), (float)500*log(whatever) all return the same, as expected.

Any ideas what's going on here?

EDIT: Following the accepted answer it turns out that in line 85 -sz is performed before the multiplication, and because sz has not been coerced into a floating point number yet, this result in something near ULONG_MAX. Still I would say this is unexpected behaviour because mathematically multiplication should happen first...

Upvotes: 0

Views: 606

Answers (1)

Danny Ruijters
Danny Ruijters

Reputation: 3429

negation is performed before the multiplication. Therefore, -sz performs negation on the unsigned number sz, which yields a very big number (unsigned numbers cannot become negative).

If you want to know how that works, have a look at the two's complement page on Wikipedia.

Since log(1 - x + x*exp(-1)) is a negative floating point number, the final result is a very big negative floating point number.

Upvotes: 1

Related Questions