Skip to content
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

rnd.wnext(long long n, int w) is broken when w <= -25 #76

Open
alex65536 opened this issue Jun 22, 2018 · 1 comment
Open

rnd.wnext(long long n, int w) is broken when w <= -25 #76

alex65536 opened this issue Jun 22, 2018 · 1 comment

Comments

@alex65536
Copy link
Contributor

The number distribution in rnd.wnext(long long n, int w) seems to be broken for negative w when it exceeds random_t::lim; (currently equal to 25). For positive w, and for rnd.wnext(int n, int w) the bug isn't reproducible.

To reproduce the bug, compile and run the following code (C++14):

#include "testlib.h"
#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;

inline void distribution(int n, int m, int w) {
	vector< pair<int, int> > knt(n);
	for (int i = 0; i < n; i++) {
		knt[i].second = i;
	}
	for (int i = 0; i < m; i++) {
		knt[rnd.wnext((int64_t)n, w)].first++;
	}
	sort(knt.begin(), knt.end());
	reverse(knt.begin(), knt.end());
	cout << "n = " << n << " m = " << m << " w = " << w << "\n";
	cout << "Distribution in top-5:\n";
	for (int i = 0; i < 5 && i < n; i++) {
		cout << knt[i].first << " " << knt[i].second << "\n";
	}
	cout << "----\n";
	cout << endl;
}

int main(int argc, char **argv) {
	registerGen(argc, argv, 1);
	distribution(100'000, 200'000, +24);
	distribution(100'000, 200'000, +25);
	distribution(100'000, 200'000, -24);
	distribution(100'000, 200'000, -25);
	return 0;
}

The output is:

n = 100000 m = 200000 w = 24
Distribution in top-5:
65 99971
65 99786
65 99389
64 99942
64 99613
----

n = 100000 m = 200000 w = 25
Distribution in top-5:
74 99694
69 99672
67 99942
66 99949
66 99839
----

n = 100000 m = 200000 w = -24
Distribution in top-5:
72 53
67 531
67 112
67 70
67 11
----

n = 100000 m = 200000 w = -25
Distribution in top-5:
128235 0
3558 1
2065 2
1426 3
1129 4
----

As you can see, the results for w=-25 greatly differ from others.

@yhx-12243
Copy link

Compare the implementation of the function wnext's, maybe the 1 - and the 1.0 / is forgotten.
(the implementation of wnext(int, int) is right, but the implementation of wnext(long long, int) and wnext(double, int) has a few bugs.)

testlib/testlib.h

Lines 809 to 818 in b288e8e

{
double p;
if (type > 0)
p = std::pow(next() + 0.0, 1.0 / (type + 1));
else
p = 1 - std::pow(next() + 0.0, 1.0 / (-type + 1));
return int(n * p);
}

testlib/testlib.h

Lines 840 to 849 in b288e8e

{
double p;
if (type > 0)
p = std::pow(next() + 0.0, 1.0 / (type + 1));
else
p = std::pow(next() + 0.0, - type + 1);
return __testlib_min(__testlib_max((long long)(double(n) * p), 0LL), n - 1LL);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants