Reputation: 11570
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
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