I'm trying to predict numbers generated by C++ rand() function. Here's a link to the code, it possibly uses: click
And here's my code that emulates rand():
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
srand(time(0));
unsigned a = rand();
unsigned b = rand();
cout << (a * 1103515245U + 12345U) % 0x7fffffffU << '\n';
cout << b << '\n'; // they should match, right? But they don't...
return 0;
}
Why doesn't my value match b?
The glibc only uses the old linear congruential generator if the TYPE_0 generator is chosen, as you can see in the code you linked. (By default, it uses the TYPE_3 generator.) This is the only case if the RNG buffer is 8 bytes large. You can force the old behavior with initstate:
char state[8];
initstate(time(0), state, 8);
unsigned a = rand();
unsigned b = rand();
cout << (a * 1103515245u + 12345u) % 0x7fffffffu << '\n';
Then you often get the same numbers, and when you don't, it's only offset by one. I haven't, at a cursory glance, been able to figure precisely why that difference happens (may edit later), but I suspect carry bit shenanigans.
EDIT: Okay, I figured it out. glibc's rand uses signed arithmetic inside, and it uses & rather than % for the modulus. This makes the one-bit difference if (a * 1103515245 + 12345) becomes negative. If you write
int a = rand();
int b = rand();
cout << (a * 1103515245 + 12345) & 0x7fffffff << '\n';
then you get the same results all the time. Well, really a and b should be int32_t for maximum portability, but I suspect that's not a concern here. Because library internals and portability is kind of a lost cause, anyway.
Adding to Wintermute's response: By default, it uses the TYPE_3 generator.
Related
why 990099009900 / 10 equals to -203843547 in c++?
#include <iostream>
using namespace std;
int main()
{
long int n = 990099009900;
cout << n / 10;
}
If you run this here:
std::cout << "limit " << std::numeric_limits<long int>::max();
You probably get 2147483647, like how it happens on Visual Studio. Try long long instead:
#include <iostream>
int main()
{
long long n = 990099009900;
std::cout << n / 10;
}
This is guaranteed to be at least 64 bit, while long int isn't (that's at least 32 bit). 32 bits aren't enough to hold 990099009900.
You need to use a long long for a number of that size in order for your code to be portable.
You are using a system where your LONG_MAX (i.e. std::numeric_limits<long>::max()) is smaller than 990099009900.
This flexibility has its drawbacks which is one reason why the fixed width types like std::int64_t were introduced.
Another approach is to use
auto n = 990099009900;
and let the compiler figure it out, although that can cause problems if you're close to the limit of the type, and you increase n.
I'm having some trouble generating a random double number. I have to create a function that takes no arguments and returns a double (between 0 and 100), the random number. Expect every time I try to create it, it returns a value of 1.
I also have to use a few symbolic constants.
#include <iostream>
#include <iomanip>
#include <ctime>
#include <cstdlib>
double randDouble();
const double UPPER_BOUND = 100.0;
const double LOWER_BOUND = 0.0;
const int ARRAY_SIZE = 100;
double randDouble()
{
int randomInt;
double randomDouble;
srand(time(NULL));
randomInt = rand() % 100 + 1;
randomDouble = LOWER_BOUND + (randomInt / RAND_MAX / ( UPPER_BOUND - LOWER_BOUND));
return randomDouble;
}
int main()
{
cout << randDouble();
return 0;
}
Another thing is, I have to use a pre-given formula for it.
lower bound + ( random integer / (maximum possible random number / (upper bound - lower bound))
First of all, you are not calling randDouble in your main, but try to print the function itself. This will always print 1 or true, depending on whether boolalpha is set. Your compiler would have warned you about that if you had enabled a more aggressive warning level. This is generally recommended.
When you fix this, you will notice that you always get zero. This is because randomInt / RAND_MAX is always zero because of truncating integer division.
When you fix that, you will notice that the returned values are not as desired because your formula is incorrect.
A lot of such problems can be avoided by using the modern std::uniform_real_distribution which already does all the hard work for you.
You can do it in a better and a cleaner way:
#include<random>
#include<iostream>
using namespace std;
int main(){
std::random_device rand_dev;
std::mt19937 gen(rand_dev());
std::uniform_real_distribution<double> dist(0, 100);
// demo.
for(int i = 0; i < 100; ++i){
// call dist(gen) whenever you need a random variable.
cout << dist(gen) << '\n';
}
return 0;
}
This code uses C++11 and won't work on earlier versions.
I am trying to calculate the combination C(40, 20) in C++, however the data types in C++ seems unable to correctly handle this calculation even though I have used long long data type. The following is my code:
#include <iostream>
long long fac(int x) {
register long long i,f = 1; // Optimize with regFunction
for(i = 1;i <= x;i++)
f *= i;
std::cout << f << std::endl;
return f;
}
// C(n,r) = n!/r!(n-r)!
long long C(long long n, long long r) {
return fac(n) / (fac(r) * fac(n - r));
}
int main(int argc, char const *argv[]) {
std::cout << C(40, 20) << std::endl;
return 0;
}
Any idea to solve this problem?
Compute C at once by executing division immediately after multiplication:
long long C(long long n, long long r)
{
long long f = 1; // Optimize with regFunction
for(auto i = 0; i < r;i++)
f = (f * (n - i)) / (i + 1);
return f ;
}
Result should be exact (divisions without remainders, until overflows) since any integer factor present in (i+1) is already present in (n -i). (Should not be too difficult to prove)
Your numbers are growing too much and that is a common problem in this kind of calculations and I am afraid there is no straightforward solution. Even if you might reduce a bit the number of multiplications you will make probably still you will end up in an overflow with long long
You might want to check those out:
https://mattmccutchen.net/bigint/
https://gmplib.org/
I know there are different algorithmic approaches on this matter. I remember there were some solutions to use strings to store integer representations and stuff but as #Konrad mentioned this might be a poor approach to the matter.
The problem is that factorials get big very quickly. 40! is too large to be stored in a long long. Luckily you don’t actually need to compute this number here since you can reduce the fraction in the calculation of C(n, r) before computing it. This yields the equation (from Wikipedia):
This works much better since k! (r! in your code) is a much smaller number than n!. However, at some point it will also break down.
Alternatively, you can also use the recurrence definition by implementing a recursive algorithm. However, this will be very inefficient (exponential running time) unless you memoise intermediate results.
A lazy way out would be to use a library that supports multiple precision, for example GNU GMP.
Once you have installed it correctly (available from the repositories on most Linux distributions), it comes down to:
adding #include <gmpxx.h> to your source file
replacing long long with mpz_class
compiling with -lgmpxx -lgmp
The source:
#include <iostream>
#include <gmpxx.h>
mpz_class fac(mpz_class x) {
int i;
mpz_class f(1); // Optimize with regFunction
for(i = 1;i <= x;i++)
f *= i;
std::cout << f << std::endl;
return f;
}
// C(n,r) = n!/r!(n-r)!
mpz_class C(mpz_class n, mpz_class r) {
return fac(n) / (fac(r) * fac(n - r));
}
int main(int argc, char const *argv[]) {
std::cout << C(40, 20) << std::endl;
return 0;
}
Compiling and running:
$ g++ comb.cpp -lgmpxx -lgmp -o comb
$ ./comb
2432902008176640000
2432902008176640000
815915283247897734345611269596115894272000000000
137846528820
If you want to be thorough, you can do a lot more, but this will get you answers.
Even if you used uint64 aka ulonglong, the max value is 18446744073709551615 whereas 40! is 815915283247897734345611269596115894272000000000 which is a bit bigger.
I recommend you to use GMP for this kind of maths
I am trying to generate a number of series of double random numbers with high precision. For example, 0.856365621 (has 9 digits after decimal).
I've found some methods from internet, however, they do generate double random number, but the precision is not as good as I request (only 6 digits after the decimal).
Thus, may I know how to achieve my goal?
In C++11 you can using the <random> header and in this specific example using std::uniform_real_distribution I am able to generate random numbers with more than 6 digits. In order to see set the number of digits that will be printed via std::cout we need to use std::setprecision:
#include <iostream>
#include <random>
#include <iomanip>
int main()
{
std::random_device rd;
std::mt19937 e2(rd());
std::uniform_real_distribution<> dist(1, 10);
for( int i = 0 ; i < 10; ++i )
{
std::cout << std::fixed << std::setprecision(10) << dist(e2) << std::endl ;
}
return 0 ;
}
you can use std::numeric_limits::digits10 to determine the precision available.
std::cout << std::numeric_limits<double>::digits10 << std::endl;
In a typical system, RAND_MAX is 231-1 or something similar to that. So your "precision" from using a method like:L
double r = rand()/RAND_MAX;
would be 1/(2<sup>31</sup)-1 - this should give you 8-9 digits "precision" in the random number. Make sure you print with high enough precision:
cout << r << endl;
will not do. This will work better:
cout << fixed << sprecision(15) << r << endl;
Of course, there are some systems out there with much smaller RAND_MAX, in which case the results may be less "precise" - however, you should still get digits down in the 9-12 range, just that they are more likely to be "samey".
Why not create your value out of multiple calls of the random function instead?
For instance:
const int numDecimals = 9;
double result = 0.0;
double div = 1.0;
double mul = 1.0;
for (int n = 0; n < numDecimals; ++n)
{
int t = rand() % 10;
result += t * mul;
mul *= 10.0;
div /= 10.0;
}
result = result * div;
I would personally try a new implementation of the rand function though or at least multiply with the current time or something..
In my case, I'm using MQL5, a very close derivative of C++ for a specific market, whose only random generator produces a random integer from 0 to 32767 (= (2^15)-1). Far too low precision.
So I've adapted his idea -- randomly generate a string of digits any length I want -- to solve my problem, more reliably (and arguably more randomly also), than anything else I can find or think of. My version builds a string and converts it to a double at the end -- avoids any potential math/rounding errors along the way (because we all know 0.1 + 0.2 != 0.3 😉 )
Posting it here in case it helps anyone.
(Disclaimer: The following is valid MQL5. MQL5 and C++ are very close, but some differences. eg. No RAND_MAX constant (so I've hard-coded the 32767). I'm not entirely sure of all the differences, so there may be C++ syntax errors here. Please adapt accordingly).
const int RAND_MAX_INCL = 32767;
const int RAND_MAX_EXCL = RAND_MAX_INCL + 1;
int iRandomDigit() {
const double dRand = rand()/RAND_MAX_EXCL; // double 0.0 <= dRand < 1.0
return (int)(dRand * 10); // int 0 <= result < 10
};
double dRandom0IncTo1Exc(const int iPrecisionDigits) {
int iPrecisionDigits2 = iPrecisionDigits;
if ( iPrecisionDigits > DBL_DIG ) { // DBL_DIG == "Number of significant decimal digits for double type"
Print("WARNING: Can't generate random number with precision > ", DBL_DIG, ". Adjusted precision to ", DBL_DIG, " accordingly.");
iPrecisionDigits2 = DBL_DIG;
};
string sDigits = "";
for (int i = 0; i < iPrecisionDigits2; i++) {
sDigits += (string)iRandomDigit();
};
const string sResult = "0." + sDigits;
const double dResult = StringToDouble(sResult);
return dResult;
}
Noted in a comment on #MasterPlanMan's answer -- the other answers use more "official" methods designed for the question, from standard library, etc. However, I think conceptually it's a good solution when faced with limitations that the other answers can't address.
Is there an implementation in gmp that allows a power function with only mpf_t's as argument? I want to do this:
mpf_t s ;
mpf_init (s);
mpf_set_d (s,boost::lexical_cast<double>(sec));
mpf_t ten,mil;
mpf_init(ten);
mpf_init(mil);
mpf_set_d(ten,10.0);
mpf_set_d(mil,0.001);
mpf_div(s,s,ten);
mpf_pow_ui(s,ten,s); //<- this doesn't work because it need an unsigned int as third argument but I need it with a mpf_t
mpf_mul(s,s,mil);
I don't think so, at least not with GNU Multi-Precision library only. But you could use mpfr, which is based on gmp and supports a mpfr_pow (mpfr_t rop, mpfr_t op1, mpfr_t op2, mpfr_rnd_t rnd) function. See here.
If you decide to do that, this could also be helpful.
There is one interesting workaround using square root mpf_sqrt_ui. From math we know that x^y = Sqrt(x)^(y * 2), so we can multiply Y many times by 2 and take square root of X same amount of times.
Thus by multiplying Y by 2 you may make it almost whole integer. And as you know there is mpf_pow_ui that does powering into whole integer.
Following code does all this. Don't forget that b should be set to high precision only to allow many times square rooting.
For simplicity I used mpf_class, this is C++ interface to mpf.
I did output to console actual mpf result value and reference value computed through std::pow from .
To avoid setting high precision is a bit more difficult, but possible e.g. through Taylor Serie like
Sqrt(1 + x) = 1 + 1/2*x - 1/8*x^2 + 1/16*x^3 - 5/128*x^4 + ...
Try it online!
#include <cmath>
#include <iostream>
#include <iomanip>
#include <gmpxx.h>
int main() {
mpf_class const b0 = 9.87654321, p0 = 1.23456789;
mpf_class b = b0, p = p0;
b.set_prec(1 << 7); p.set_prec(1 << 7);
int const sqrt_cnt = 48;
for (int i = 0; i < sqrt_cnt; ++i)
mpf_sqrt(b.get_mpf_t(), b.get_mpf_t());
mpf_mul_2exp(p.get_mpf_t(), p.get_mpf_t(), sqrt_cnt);
mpf_pow_ui(b.get_mpf_t(), b.get_mpf_t(), std::lround(p.get_d()));
std::cout << std::fixed << std::setprecision(12) << "Actual "
<< b.get_d() << ", Reference " << std::pow(b0.get_d(), p0.get_d())
<< std::endl;
}
Output:
Actual 16.900803674719, Reference 16.900803674719