New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
math/rand,math/rand/v2: ExpFloat64 can sometimes return exactly 0 #65432
Comments
CC @rsc maybe? |
I think this is a documentation issue. Wikipedia's article on the exponential distribution lists the support as [0, +inf), and I'm not aware of any particular reason to exclude 0 as a variate. (Not to say no such reason exists.) The way to exclude 0 and +inf as outputs of the exponential generator without introducing bias would be by explicit rejection: check for the conditions we care about and
It's probably unlikely to find a seed with math/rand's default Source which will lead to this situation in feasible time, but it's possible to construct one with math/rand/v2's PCG. Any state which produces an x such that 0x00e290a139 <= With the DXSM step, finding such an x is beyond what I know how to do, but I believe there are techniques better than brute force to do it. Once an appropriate state is found, NewPCG lets us construct a generator with it directly. It seems more likely to me that +inf would be a problem than 0, but given it's been a possible output since ExpFloat64 was introduced and this is the first issue about it, I'm less certain. Maybe it has been a problem but it's too rare to diagnose with math/rand's source, though. |
I'm fine with the 0 just being a documentation change. I filed this is because I caught a 0 'in the wild', running a program generating tens of billions of ExpFloat64 results, then being surprised to see my program crash on a 0. It was trivial to adjust my code to support the range being [0, ...] instead of (0, ...], though. The reason +Inf hasn't been reported before is probably because no one ever noticed. The odds of hitting it on any "real" rng source is extraordinarily low, since you not only have to get a 0 float64 (I think 1/2^63 odds under the v1 rand.Float64, 1/2^53 in v2), but it also has to come after two if statements that I think require ~1/2^11.3 odds. It's probably never happened even once before now; you would have to specifically design an rng source/seed to hit it. |
Managed to find a PCG seed that triggers a +Inf rand/v2 ExpFloat64 output: https://go.dev/play/p/uGeWg2mcvDw?v=gotip |
Go version
go version go1.21.6 windows/amd64
Output of
go env
in your module/workspace:What did you do?
https://go.dev/play/p/-5HbPTMP5X9
Running ExpFloat64() after a few iterations on a brute-forced seed that triggers this case.
What did you see happen?
ExpFloat64() returns 0.0 exactly.
What did you expect to see?
Per the function's comment: "
ExpFloat64 returns an exponentially distributed float64 in the range (0, +math.MaxFloat64]
", so a value larger than 0 was expected.This should occur whenever r.Uint32() at https://cs.opensource.google/go/go/+/refs/tags/go1.21.6:src/math/rand/exp.go;l=32 returns 0 exactly. This appears to still exist in math/rand/v2.
Note: as maybe a separate issue, ExpFloat64 can also theoretically return +Inf, also not in the range specified by the function comment, when r.Float64() returns exactly 0.0 at https://cs.opensource.google/go/go/+/refs/tags/go1.21.6:src/math/rand/exp.go;l=39 - though this is extremely unlikely (example of a specially crafted "random" source to trigger a +Inf https://go.dev/play/p/sugD7822wW5)
The text was updated successfully, but these errors were encountered: