C++ Faulty Random Numbers [duplicate] - c++

This question already has answers here:
How unique is rand() in C?
(4 answers)
Closed 8 years ago.
I'm creating a machine that generates a shotgun with random components that effect the overall quality of the gun. I'm having a problem generating the random parts that will comprise the shotgun. There are 4 parts that have to be generated. When I created each of these functions, I tested them individually and they all work but when I try to put them together with the createChromo() function, the numbers are individually random. I should be getting results like 2131 and 1332, but I keep getting 1111 or 1112 or 2221 or 2222....Here is the code:
int generateButt()
{
srand(unsigned(time(NULL)));
int buttType = rand() % 3 + 1;
if(buttType == 1)
{
accuracy = rand() % ((5 - 2) + 2) / 10.0;
fireRate = fireRate - 0.3;
}
if(buttType == 2)
{
accuracy = rand() % ((8 + 5) + 5)/ 10.0;
fireRate = fireRate - 0.2;
}
if(buttType == 3)
{
accuracy = rand() % ((11 + 8) + 8) / 10.0;
fireRate = fireRate - 0.1;
}
return buttType;
}
int generateBarrel()
{
srand(unsigned(time(NULL)));
int barrelType = rand() % 3 + 1;
if(barrelType == 1)
{
range = rand() % (16 - 5) + 5;
power = power + 3;
}
if(barrelType == 2)
{
range = rand() % (21 - 16) + 16;
power = power + 1;
}
if(barrelType == 3)
{
range = rand() % (26 + 21) + 21;
power = power - 1;
}
return barrelType;
}
int generateBullet()
{
srand(unsigned(time(NULL)));
int bulletType = rand() % 3 + 1;
if(bulletType == 1)
{
power = rand() % (16 - 10) + 10;
range = range + 5;
}
if(bulletType == 2)
{
power = rand() % (26 - 16) + 16;
range = range + 1;
}
if(bulletType == 3)
{
power = rand() % (35 - 26) + 26;
range = range - 2;
}
return bulletType;
}
int generateAction()
{
srand(unsigned(time(NULL)));
int actionType = rand() % 2 + 1;
if(actionType == 1)
{
fireRate = 1.5;
accuracy = accuracy + 0.2;
}
if(actionType == 2)
{
fireRate = 2.0;
accuracy = accuracy - 0.1;
}
return actionType;
}
void createChromo(int a, int b, int c, int d)
{
cout <<a<<b<<c<<d<<"\n";
}
int main()
{
for(int i = 0; i < popSize; i++)
createChromo(generateButt(), generateBarrel(), generateBullet(), generateAction());
system("pause");
return 0;
}

You're calling srand each time you call either function. What srand does is seed the generator for a new string of random numbers. You base that seed off of the current second, so if it's called in the same second, the seed will be the same as last time, and thus the sequence of random numbers obtained from rand() will be as well.
Call srand(time(NULL)); once at the beginning of your program to just have one sequence, and keep using the next number in that one sequence instead of starting the same sequence over.
If you have access to C++11, you might consider using the <random> header as well.

the concept of random does not exist in the entire computation world
the function srand() is used to set a seed for the rand() function
if you set 2 different seed your generator of pseudo-random numbers will behave in 2 different ways

Related

Result not matching up to Set Variable

I am scratching my brain off trying to figure this one out.
Why are running backs getting 60+ carries a game with this code? I just don't get it.
The team is an array, this for loop is only supposed to run 25 times AT MOST. I've even tried setting the for loop to (int g = 1; g < 20; g++) and yet still it is coming up with 60+ carries a game for no reason. Any help?
hold3 = rand() % (10 - 15 + 1) + 15;
for(int g = 1; g < hold3; g++){
hold = rand() % (15 - team[u].elusivness[2] + 1) + team[u].elusivness[2];
if(hold == 13 || hold == 14){
team[u].carries[2]++;
hold = rand() % (17 - team[u].strength[2] + 1) + team[u].strength[2];
if(hold == 13){
team[u].rushingtouchdowns[2]++;
hold = rand() % 25 + 5;
team[u].rushingyards[2] += hold;
}else{
hold = rand() % (12 - team[u].speed[2] + 1) + team[u].speed[2];
if(hold == 12){
hold = rand() % 15 + 5;
team[u].rushingyards[2] += hold;
}else{
hold = rand() % 5 + 1;
team[u].rushingyards[2] += hold;
}
}
}
}
you are trying getting mod from deviser below 0. hold3 = rand() % (10 - 15 + 1) + 15;

Cpp program not giving output

I am creating a script that calculates the sum of first n Fibonacci numbers and returns the last digit of the sum.
The python script works perfect but the C++ script does not and the logic is same.
Any help will be appreciated.
Python Code
def calc_fib(n):
f = [0, 1]
for i in range(2, 61):
f.insert(i, (f[i-1] + f[i-2]) % 10)
rem = n % 60
quotient = (n - rem) / 60
return int((sum(f) * quotient + sum(f[0: rem+1])) % 10)
n = int(input())
print(calc_fib(n))
C++ Code
#include <iostream>
#include <vector>
#include <numeric>
using namespace std;
long long fibonacci_sum_last_digit(long long n) {
vector<int> f(n + 1);
f[0] = 0;
f[1] = 1;
for (int i = 2; i <= 60; i++){
f[i] = (f[i-1] + f[i-2]) % 10;
}
int rem = n % 60;
int quotient = (n - rem) / 60;
return (accumulate(f.begin(), f.end(), 0) * quotient + accumulate(f.begin(), f.begin() + rem + 1, 0)) % 10;
}
int main() {
int n;
cin >> n;
if (n <= 1)
cout << n;
else
cout << fibonacci_sum_last_digit(n) << '\n';
return 0;
}
vector<int> f(n + 1);
f[0] = 0;
f[1] = 1;
for (int i = 2; i <= 60; i++){
f[i] = (f[i-1] + f[i-2]) % 10;
}
The vector is size n+1 and you access until 60 => it's a bug
This should fix :
vector<int> f(60 + 1);
Or
vector<int> f;
f.push_back(0);
f.push_back(1);
for (int i = 2; i <= 60; i++){
f.push_back((f[i-1] + f[i-2]) % 10);
}

Calculating mod m for large Fibonacci numbers

I am getting two warning (narrowing conversion && control may reach end of non-void function) with the following code. The code compiles however, when I run it it gives this message : Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
The code is compiled using CLion on Ubuntu
// calculate F(n) mod m
#include <iostream>
#include <cmath>
long long Fiobonacci(long long n) { // Fast calculation of Fibonacci number using 'fast doubling'
if (n == 0)
return 0;
else if (n % 2 == 0)
return Fiobonacci(n / 2) * (2 * Fiobonacci(n / 2 + 1) - Fiobonacci(n / 2));
else
return std::pow(Fiobonacci((n + 1) / 2), 2) + std::pow(Fiobonacci((n - 1) / 2), 2);
}
long long GetPissanoPeriod(long long m){
for (long long i = 0; i <= 6 * m ; ++i){
if (Fiobonacci(i) % m == 0){ // if an element is zero it might be followed by a 1
if(Fiobonacci(i+1) % m == 1)
return i+1;
}
}
}
int main() {
long long n, m;
std::cin >> n >> m;
long long period = GetPissanoPeriod(m);
long long res = Fiobonacci(n % period) % m;
std::cout << res << 'n';
}
See the modified code below.
#include <iostream>
#include <cmath>
using namespace std;
long long pow2(long long x)
{
return x * x;
}
long long Fibonacci(long long n) { // Fast calculation of Fibonacci number using 'fast doubling'
if (n == 0)
return 0;
else if(n <= 2)
return 1;
else if (n % 2 == 0)
return Fibonacci(n / 2) * (2 * Fibonacci(n / 2 + 1) - Fibonacci(n / 2));
else
return pow2(Fibonacci((n/2 + 1) / 2), 2) + pow2(Fibonacci((n / 2)), 2);
}
long long GetPisanoPeriod(long long m){
for (long long i = 2; i <= m * m ; ++i){
if (Fibonacci(i) % m == 0){ // if an element is zero it might be followed by a 1
if(Fibonacci(i+1) % m == 1){
return i - 1;
}
}
}
return 1;
}
int main() {
long long n, m;
std::cin >> n >> m;
long long period = GetPisanoPeriod(m);
long long res = Fibonacci(n % period) % m;
std::cout << "res" << res<<endl;
}
control may reach end of non-void function error is due to not returning value from GetPisanoPeriod. as pointed out by #JaMiT
The segmentation fault was due to the incorrect termination condition of function Fibonacci.
Fibonacci series is defined as below.
Fn = Fn-1 + Fn-2
with seed values
F0 = 0 and F1 = 1
Meaning there should be a termination condition for n = 0 and n = 1.
For n = 2 You don't have to call recursion can simply return 1.
Other than that, There were corrections in Fibonacci calculation formula as you can see.
In GetPisanoPeriod The control has to start from 2. otherwise it would always return 0.

Partition function based on Euler's formula

I am trying to find the partitions of a number using the Euler's formula for that:
It produces results like:
P(3) = P(2) + P(1) = 3
P(4) = P(3) + P(2) = 3+ 2 = 5
P(5) = P(4) + P(3) - P(0) = 5 + 3 - 1 = 7
P(6) = P(5) + P(4) - P(1) = 7 + 5 - 1 = 11 and so on..
* P(0) = 1
It produces two positive and then two negative values and so on.
I am using recursion for that but the code goes into an infinite loop without producing any result.
long result = 0;
long counter = 0;
class Euler
{
public:
long Partition(long n)
{
int exponent = 0;
if (n < 0)
{
return 0;
}
else
{
counter = counter + 1;
exponent = pow(-1, counter - 1) ;
if (n == 0)
{
n = 1;
}
return Partition((exponent * (n - ( (counter * ( (3 * counter) - 1)) / 2)))) +
Partition(((exponent * (n - ( (counter * ( (3 * counter) + 1)) / 2)) )));
}
}
};
int main(int argc, char** argv)
{
long result= 0;
long a = 3;
Euler * obj = new Euler();
long s = obj->Partition(a);
std::cout << s;
return 0;
}
Your global counter is modified by the first call to Partition, so the second one operates on a different one; in fact, the counter changes more or less unpredictably.
Do not use globals.

How to find the sum of elements on even position?

How to find the sum of elements on even position without usage of arrays etc, only normal operations?
For example:
159
Sum = 5.
159120
Sum = 5+1+0 = 6.
My work:
int sumofdigits(int x)
{
int sum = 0;
while(x > 0){
if (x % 100 != 0)
sum += x % 100;
x /= 100;
}
return sum;
}
Since you're counting "even" digits from the left, you first need to count the number of digits in order to know whether the least significant digit is even or not:
int sumOfEvenDigits(int x)
{
// First, count the number of digits
int digitCount = 0;
int tmp = x;
while(tmp) {
tmp /= 10;
digitCount++;
}
// If the number of digits is odd, throw away the least significant digit
if(digitCount % 2 == 1)
x /= 10;
// Keep adding the least significant digit, and throwing away two digits until you're done.
int sum = 0;
while(x){
sum += x % 10;
x /= 100;
}
return sum;
}
int accumulateIfEvenPos(int num, int pos) {
if (num == 0) return 0;
int digit = num % 10;
int next = num / 10;
return pos & 1 ? digit + accumulateIfOdd(next, ++pos) : accumulateIfOdd(next, ++pos);
}
You call it with pos 1 initially - demo here.
Well simple modification should do the trick.
int main()
{
int x = 1549;
//Get the number of digits
int length = snprintf(NULL, 0, "%i", x);
int sum = 0;
while(x > 0){
if (x % 100 != 0) {
//check if the number of digits is even to start from the last digit
if (length % 2 == 0) {
sum += x % 10;
x /= 10;
}
else {
x /= 10;
sum += x % 10;
}
x /= 10;
}
}
cout << sum << endl;
return 0;
}
EDIT: Solved the problem/bug in the algorithm. This might not be the best answer but I didn't want to completely write a different one(than the answer before edit).
You will need to have an index variable that keeps track of the position:
unsigned int digit_position = 0;
while (x > 0)
{
unsigned int digit_value = x % 10;
if (digit_position is even)
{
// Add digit_value to sum
}
// Shift value right one digit
x /= 10;
++digit_position;
}
There may be other methods using a position variable and the pow() function. But that is left as an exercise for the reader.