I was reading through How can I write a power function myself? and the answer given by dan04 caught my attention mainly because I am not sure about the answer given by fortran, but I took that and implemented this:
#include <iostream>
using namespace std;
float pow(float base, float ex){
// power of 0
if (ex == 0){
return 1;
// negative exponenet
}else if( ex < 0){
return 1 / pow(base, -ex);
// even exponenet
}else if ((int)ex % 2 == 0){
float half_pow = pow(base, ex/2);
return half_pow * half_pow;
//integer exponenet
}else{
return base * pow(base, ex - 1);
}
}
int main(){
for (int ii = 0; ii< 10; ii++){\
cout << "pow(" << ii << ".5) = " << pow(ii, .5) << endl;
cout << "pow(" << ii << ",2) = " << pow(ii, 2) << endl;
cout << "pow(" << ii << ",3) = " << pow(ii, 3) << endl;
}
}
though I am not sure if I translated this right because all of the calls giving .5 as the exponent return 0. In the answer it states that it might need a log2(x) based on a^b = 2^(b * log2(a)), but I am unsure about putting that in as I am unsure where to put it, or if I am even thinking about this right.
NOTE: I know that this might be defined in a math library, but I don't need all the added expense of an entire math library for a few functions.
EDIT: does anyone know a floating-point implementation for fractional exponents? (I have seen a double implementation, but that was using a trick with registers, and I need floating-point, and adding a library just to do a trick I would be better off just including the math library)
I have looked at this paper here which describes how to approximate the exponential function for double precision. After a little research on Wikipedia about single precision floating point representation I have worked out the equivalent algorithms. They only implemented the exp function, so I found an inverse function for the log and then simply did
POW(a, b) = EXP(LOG(a) * b).
compiling this gcc4.6.2 yields a pow function almost 4 times faster than the standard library's implementation (compiling with O2).
Note: the code for EXP is copied almost verbatim from the paper I read and the LOG function is copied from here.
Here is the relevant code:
#define EXP_A 184
#define EXP_C 16249
float EXP(float y)
{
union
{
float d;
struct
{
#ifdef LITTLE_ENDIAN
short j, i;
#else
short i, j;
#endif
} n;
} eco;
eco.n.i = EXP_A*(y) + (EXP_C);
eco.n.j = 0;
return eco.d;
}
float LOG(float y)
{
int * nTemp = (int*)&y;
y = (*nTemp) >> 16;
return (y - EXP_C) / EXP_A;
}
float POW(float b, float p)
{
return EXP(LOG(b) * p);
}
There is still some optimization you can do here, or perhaps that is good enough.
This is a rough approximation but if you would have been satisfied with the errors introduced using the double representation, I imagine this will be satisfactory.
I think the algorithm you're looking for could be 'nth root'. With an initial guess of 1 (for k == 0):
#include <iostream>
using namespace std;
float pow(float base, float ex);
float nth_root(float A, int n) {
const int K = 6;
float x[K] = {1};
for (int k = 0; k < K - 1; k++)
x[k + 1] = (1.0 / n) * ((n - 1) * x[k] + A / pow(x[k], n - 1));
return x[K-1];
}
float pow(float base, float ex){
if (base == 0)
return 0;
// power of 0
if (ex == 0){
return 1;
// negative exponenet
}else if( ex < 0){
return 1 / pow(base, -ex);
// fractional exponent
}else if (ex > 0 && ex < 1){
return nth_root(base, 1/ex);
}else if ((int)ex % 2 == 0){
float half_pow = pow(base, ex/2);
return half_pow * half_pow;
//integer exponenet
}else{
return base * pow(base, ex - 1);
}
}
int main_pow(int, char **){
for (int ii = 0; ii< 10; ii++){\
cout << "pow(" << ii << ", .5) = " << pow(ii, .5) << endl;
cout << "pow(" << ii << ", 2) = " << pow(ii, 2) << endl;
cout << "pow(" << ii << ", 3) = " << pow(ii, 3) << endl;
}
return 0;
}
test:
pow(0, .5) = 0.03125
pow(0, 2) = 0
pow(0, 3) = 0
pow(1, .5) = 1
pow(1, 2) = 1
pow(1, 3) = 1
pow(2, .5) = 1.41421
pow(2, 2) = 4
pow(2, 3) = 8
pow(3, .5) = 1.73205
pow(3, 2) = 9
pow(3, 3) = 27
pow(4, .5) = 2
pow(4, 2) = 16
pow(4, 3) = 64
pow(5, .5) = 2.23607
pow(5, 2) = 25
pow(5, 3) = 125
pow(6, .5) = 2.44949
pow(6, 2) = 36
pow(6, 3) = 216
pow(7, .5) = 2.64575
pow(7, 2) = 49
pow(7, 3) = 343
pow(8, .5) = 2.82843
pow(8, 2) = 64
pow(8, 3) = 512
pow(9, .5) = 3
pow(9, 2) = 81
pow(9, 3) = 729
I think that you could try to solve it by using the Taylor's series,
check this.
http://en.wikipedia.org/wiki/Taylor_series
With the Taylor's series you can solve any difficult to solve calculation such as 3^3.8 by using the already known results such as 3^4. In this case you have
3^4 = 81 so
3^3.8 = 81 + 3.8*3( 3.8 - 4) +..+.. and so on depend on how big is your n you will get the closer solution of your problem.
I and my friend faced similar problem while we're on an OpenGL project and math.h didn't suffice in some cases. Our instructor also had the same problem and he told us to seperate power to integer and floating parts. For example, if you are to calculate x^11.5 you may calculate sqrt(x^115, 10) which may result more accurate result.
Reworked on #capellic answer, so that nth_root works with bigger values as well.
Without the limitation of an array that is allocated for no reason:
#include <iostream>
float pow(float base, float ex);
inline float fabs(float a) {
return a > 0 ? a : -a;
}
float nth_root(float A, int n, unsigned max_iterations = 500, float epsilon = std::numeric_limits<float>::epsilon()) {
if (n < 0)
throw "Invalid value";
if (n == 1 || A == 0)
return A;
float old_value = 1;
float value;
for (int k = 0; k < max_iterations; k++) {
value = (1.0 / n) * ((n - 1) * old_value + A / pow(old_value, n - 1));
if (fabs(old_value - value) < epsilon)
return value;
old_value = value;
}
return value;
}
float pow(float base, float ex) {
if (base == 0)
return 0;
if (ex == 0){
// power of 0
return 1;
} else if( ex < 0) {
// negative exponent
return 1 / pow(base, -ex);
} else if (ex > 0 && ex < 1) {
// fractional exponent
return nth_root(base, 1/ex);
} else if ((int)ex % 2 == 0) {
// even exponent
float half_pow = pow(base, ex/2);
return half_pow * half_pow;
} else {
// integer exponent
return base * pow(base, ex - 1);
}
}
int main () {
for (int i = 0; i <= 128; i++) {
std::cout << "pow(" << i << ", .5) = " << pow(i, .5) << std::endl;
std::cout << "pow(" << i << ", .3) = " << pow(i, .3) << std::endl;
std::cout << "pow(" << i << ", 2) = " << pow(i, 2) << std::endl;
std::cout << "pow(" << i << ", 3) = " << pow(i, 3) << std::endl;
}
std::cout << "pow(" << 74088 << ", .3) = " << pow(74088, .3) << std::endl;
return 0;
}
This solution of MINE will be accepted upto O(n) time complexity
utpo input less then 2^30 or 10^8
IT will not accept more then these inputs
It WILL GIVE TIME LIMIT EXCEED warning
but easy understandable solution
#include<bits/stdc++.h>
using namespace std;
double recursive(double x,int n)
{
// static is important here
// other wise it will store same values while multiplying
double p = x;
double ans;
// as we multiple p it will multiply it with q which has the
//previous value of this ans latter we will update the q
// so that q has fresh value for further test cases here
static double q=1; // important
if(n==0){ ans = q; q=1; return ans;}
if(n>0)
{
p *= q;
// stored value got multiply by p
q=p;
// and again updated to q
p=x;
//to update the value to the same value of that number
// cout<<q<<" ";
recursive(p,n-1);
}
return ans;
}
class Solution {
public:
double myPow(double x, int n) {
// double q=x;double N=n;
// return pow(q,N);
// when both sides are double this function works
if(n==0)return 1;
x = recursive(x,abs(n));
if(n<0) return double(1/x);
// else
return x;
}
};
For More help you may try
LEETCODE QUESTION NUMBER 50
**NOW the Second most optimize code pow(x,n) **
logic is that we have to solve it in O(logN) so we devide the n by 2
when we have even power n=4 , 4/2 is 2 means we have to just square it (22)(22)
but when we have odd value of power like n=5, 5/2 here we have square it to get
also the the number itself to it like (22)(2*2)*2 to get 2^5 = 32
HOPE YOU UNDERSTAND FOR MORE YOU CAN VISIT
POW(x,n) question on leetcode
below the optimized code and above code was for O(n) only
*
#include<bits/stdc++.h>
using namespace std;
double recursive(double x,int n)
{
// recursive calls will return the whole value of the program at every calls
if(n==0){return 1;}
// 1 is multiplied when the last value we get as we don't have to multiply further
double store;
store = recursive(x,n/2);
// call the function after the base condtion you have given to it here
if(n%2==0)return store*store;
else
{
return store*store*x;
// odd power we have the perfect square multiply the value;
}
}
// main function or the function for indirect call to recursive function
double myPow(double x, int n) {
if(n==0)return 1;
x = recursive(x,abs(n));
// for negatives powers
if(n<0) return double(1/x);
// else for positves
return x;
}
Related
My goal is to figure out whether each element of an array is a prime or not.
Example:
Input: int A[5]={1,2,3,4,5}
Output: bool P[5]={0,1,1,0,1}
The problem is the array size is up to 10^6. I tried the most efficient prime-checking algorithm
(code: http://cpp.sh/9ewxa) but just the "cin" and "prime_checking" take really long time. How should I solve this problem, Thanks.
Your "most efficient" prime test is actually horribly inefficient. Something like the Miller-Rabin primality test is much faster on a one by one basis. If your input are below 4.3 billion (i.e. uint32_t) then you only need to do 3 tests: a = 2, 7, and 61. For numbers in the uint64_t range it's 12 tests.
If you have a large array of integers then computing all primes up to some maximum might be faster than repeated tests. See Sieve of Eratosthenes for a good way to compute all primes fast. But it's impractical if your input numbers can be larger than 4 billion due to the memory required.
Here is some code that computes a Sieve up to UINT32_MAX+1 and then checks Miller-Rabin has the same results as the sieve: https://gist.github.com/mrvn/137fb0c8a5c78dbf92108b696ff82d92
#include <iostream>
#include <cstdint>
#include <array>
#include <ranges>
#include <cassert>
#include <bitset>
uint32_t pow_n(uint32_t a, uint32_t d, uint32_t n) {
if (d == 0) return 1;
if (d == 1) return a;
uint32_t t = pow_n(a, d / 2, n);
t = ((uint64_t)t * t) % n;
if (d % 2 == 0) {
return t;
} else {
return ((uint64_t)t * a) % n;
}
};
bool test(uint32_t n, unsigned s, uint32_t d, uint32_t a) {
//std::cout << "test(n = " << n << ", s = " << s << ", d = " << d << ", a = " << a << ")\n";
uint32_t x = pow_n(a ,d ,n);
//std::cout << " x = " << x << std::endl;
if (x == 1 || x == n - 1) return true;
for (unsigned i = 1; i < s; ++i) {
x = ((uint64_t)x * x) % n;
if (x == n - 1) return true;
}
return false;
}
bool is_prime(uint32_t n) {
static const std::array witnesses{2u, 3u, 5u, 7u, 11u, 13u, 17u, 19u, 23u, 29u, 31u, 37u};
static const std::array bounds{
2'047llu, 1'373'653llu, 25'326'001llu, 3'215'031'751llu,
2'152'302'898'747llu, 3'474'749'660'383llu,
341'550'071'728'321llu, 341'550'071'728'321llu /* no bounds for 19 */,
3'825'123'056'546'413'051llu,
3'825'123'056'546'413'051llu /* no bound for 29 */,
3'825'123'056'546'413'051llu /* no bound for 31 */,
(unsigned long long)UINT64_MAX /* off by a bit but it's the last bounds */,
};
static_assert(witnesses.size() == bounds.size());
if (n == 2) return true; // 2 is prime
if (n % 2 == 0) return false; // other even numbers are not
if (n <= witnesses.back()) { // I know the first few primes
return (std::ranges::find(witnesses, n) != std::end(witnesses));
}
// write n = 2^s * d + 1 with d odd
unsigned s = 0;
uint32_t d = n - 1;
while (d % 2 == 0) {
++s;
d /= 2;
}
// test widtnesses until the bounds say it's a sure thing
auto it = bounds.cbegin();
for (auto a : witnesses) {
//std::cout << a << " ";
if (!test(n, s, d, a)) return false;
if (n < *it++) return true;
}
return true;
}
template<std::size_t N>
auto composite() {
std::bitset<N / 2 + 1> is_composite;
for (uint32_t i = 3; (uint64_t)i * i < N; i += 2) {
if (is_composite[i / 2]) continue;
for (uint64_t j = i * i; j < N; j += 2 * i) is_composite[j / 2] = true;
}
return is_composite;
}
bool slow_prime(uint32_t n) {
static const auto is_composite = composite<UINT32_MAX + 1llu>();
if (n < 2) return false;
if (n == 2) return true;
if (n % 2 == 0) return false;
return !is_composite.test(n / 2);
}
int main() {
/*
std::cout << "2047: ";
bool fast = is_prime(2047);
bool slow = slow_prime(2047);
std::cout << (fast ? "fast prime" : "");
std::cout << (slow ? "slow prime" : "");
std::cout << std::endl;
*/
//std::cout << "2: prime\n";
for (uint64_t i = 0; i <= UINT32_MAX; ++i) {
if (i % 1000000 == 1) { std::cout << "\r" << i << " "; std::cout.flush(); }
bool fast = is_prime(i);
bool slow = slow_prime(i);
if (fast != slow) std::cout << i << std::endl;
assert(fast == slow);
//std::cout << i << ": " << (is_prime(i) ? "prime" : "") << std::endl;
}
}
The sieve takes ~15s to compute and uses 256MB of memory, verifying Miller-Rabin takes ~12m45s or 765 times slower than the sieve. Which tells me that if you are testing more than 85 million 32bit numbers for primes then just compute them all with a sieve. Since the sieve is O(n^2) it only gets better if your maximum input is smaller.
Problem is :
Write a function that as an input argument receives a three-digit positive number and as a result has to get the sum between the largest and the smallest number obtained by the same 3 digits divided by the median digit.
Example: input argument to function 438
The largest with the same digits is 843, the smallest is 348, so it should be calculated (843 + 348) / 4.
I have tried it and got the result ok but my code seems to complicated so iam asking is there a better way to do it?
Thanks in advance
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int check(int x) {
int a, b, c, biggestNum, smallestNum, medianNum;
a = x / 100;
b = (x / 10) % 10;
c = x % 10;
if (a > b && a > c && b > c) {
biggestNum= a * 100 + b * 10 + c;
smallestNum= c * 100 + b * 10 + a;
medianNum= b;
}
else if (a > b && a > c && b < c) {
biggestNum= a * 100 + c * 10 + b;
smallestNum= b * 100 + c * 10 + a;
medianNum= c;
}
else if (b > a && b > c && a < c) {
biggestNum= b * 100 + c * 10 + a;
smallestNum= a * 100 + c * 10 + b;
medianNum= c;
}
else if (b > a && b > c && a > c) {
biggestNum= b * 100 + a * 10 + c;
smallestNum= c * 100 + a * 10 + b;
medianNum= a;
}
else if (c > a && c > b && a > b) {
biggestNum= c * 100 + a * 10 + b;
smallestNum= b * 100 + a * 10 + c;
medianNum= a;
}
else if (c > a && c > b && a < b) {
biggestNum= c * 100 + b * 10 + a;
smallestNum= a * 100 + b * 10 + c;
medianNum= b;
}
cout << "Smallest number is: " << smallestNum<< " ,biggest is: " << biggestNum << " and median is: " << medianNum<< "." << endl;
return (biggestNum + smallestNum) / medianNum;
}
int main() {
cout << "Enter one 3 digit positive number: ";
int x;
cin >> x;
float result = check(x);
cout << "The result is: " << result << "." << endl;
system("pause");
return 0;
}
The posted code can't really produce the right answer, considering that the result is calculated with integer arithmetic:
int check(int x) // <- note the type of the returned value
{
int biggestNum, smallestNum, medianNum;
// ...
return (biggestNum + smallestNum) / medianNum; // <- This is an integer division
}
int main()
{
int x;
// ...
float result = check(x); // Now it's too late to get the right result
}
The logic also doesn't consider all the possible cases, as a matter of fact it ignores duplicated digits and the big if else if construct, lacking a default branch (a final unconditioned else), leaves those uninitialized variables undetermined so that the following operation gives a meaningless result.
Given the assignment restrictions, I'd write something like the following
#include <utility>
// The assignment is about 3-digit numbers, you should check that x is actually in
// the range [100, 999]. Note that one of the extremes is a special case.
// Well, both, actually.
double I_ve_no_idea_how_to_name_this(int x)
{
constexpr int base = 10;
int smallest = x % base;
x /= base;
int median = x % base;
x /= base;
// Note that this "works" (extracting the third digit) even if
// x isn't a 3-digit number. If you can assure the input is well
// defined, you can simplify this.
int biggest = x % base;
// Now we can sort the previous variables.
using std::swap;
if ( median < smallest ) {
swap(median, smallest);
}
// Now I know that smallest <= median
if ( biggest < median ) {
swap(biggest, median);
}
// Now I know that median <= biggest
// ...
// Is that enough or am I missing something here?
// Please think about it before running the code and test it.
// Once the variables are sorted, the result is easily calculated
return (biggest + smallest + base * (2 * median + base * (biggest + smallest)))
/ static_cast<double>(median);
}
First, you should use more descriptive variable names and should initialize each variable on definition. These two steps help greatly in squashing bugs in complex programs. I know this one isn't complex, but it's a good habit to have. Second, the standard library can help with finding the largest and smallest digit, which then makes the rest simple. So here's an example without any if statements.
Finally, using namespace std; is a bad practice and should be avoided.
double check(int x)
{
int a = x / 100;
int b = (x / 10) % 10;
int c = x % 10;
int bigdigit = std::max({ a, b, c }); // find largest
int smalldigit = std::min({ a, b, c }); //find smallest
int middledigit = a + b + c - bigdigit - smalldigit; // sum of all digits minus largest and smallest gives the remaining one
int biggest = smalldigit + middledigit * 10 + bigdigit * 100;
int smallest = smalldigit * 100 + middledigit * 10 + bigdigit;
std::cout << "biggest: " << biggest << '\n';
std::cout << "smallest: " << smallest << '\n';
std::cout << "median: " << middledigit << '\n';
return (1.0 * biggest + 1.0 * smallest) / (1.0 * middledigit); --using double instead of int, as result could be fractional
}
try this...
int check(int x) {
int a,b,c,temp;
a = x/100;
b = (x/10)%10;
c = x%10;
if(b>a){
temp=a;
a=b;
b=temp;
}
if(c>b){
temp=b;
b=c;
c=temp;
}
if(b>a){
temp=a;
a=b;
b=temp;
}
cout << "smallest: " << a+(b*10)+(c*100) << "\n";
cout << "biggest: " << (a*100)+(b*10)+c << "\n";
cout << "median: " << b << "\n";
return (((a+c)*100)+(2*b*10)+(a+c))/b;
}
check this check function.
int check(int x) {
if(x >= 1000) x %= 1000; //or return -1;
//get digits
int M = x/100;
int C = (x/10)%10;
int m = x%10;
//unrolled bubble sort.
if(M < C) swap(M,C);
if(C < m) swap(C,m);
if(M < C) swap(M,C);
//simplified formula
return ((m+M)*(101))/C + 20;
}
//derivation of formula
B = M*100 + C*10 + m;
s = m*100 + C*10 + M;
B+s = (m+M)*100 + C*20 + (m+M)
= (m+M)*(100 + 1) + C*20
(B+s)/C = ((m+M)*(100 + 1) + C*20)/C
= ((m+M)*(101))/C + 20
doing a C++ approximation of Pi using a random number generator, output works exactly as expected on my AMD 64 machine running Ubuntu, however on my school machine the second algorithm I've implemented is broken, and would love some insight as to why. Code is as follows:
#ifndef RANDOMNUMBER_H_
#define RANDOMNUMBER_H_
class RandomNumber {
public:
RandomNumber() {
x = time(NULL);
m = pow(2, 19); //some constant value
M = 65915 * 7915; //multiply of some simple numbers p and q
method = 1;
}
RandomNumber(int seed) {
x = ((seed > 0) ? seed : time(NULL));
m = pow(2, 19); //some constant value
method = 1; //method number
M = 6543 * 7915; //multiply of some simple numbers p and q
}
void setSeed(long int seed) {
x = seed; //set start value
}
void chooseMethod(int method) {
this->method = ((method > 0 && method <= 2) ? method : 1); //choose one of two method
}
long int linearCongruential() { //first generator, that uses linear congruential method
long int c = 0; // some constant
long int a = 69069; //some constant
x = (a * x + c) % m; //solution next value
return x;
}
long int BBS() { //algorithm Blum - Blum - Shub
x = (long int) (pow(x, 2)) % M;
return x;
}
double nextPoint() { //return random number in range (-1;1)
double point;
if (method == 1) //use first method
point = linearCongruential() / double(m);
else
point = BBS() / double(M);
return point;
}
private:
long int x; //current value
long int m; // some range for first method
long int M; //some range for second method
int method; //method number
};
#endif /* RANDOMNUMBER_H_ */
and test class:
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <iomanip>
#include "RandomNumber.h"
using namespace std;
int main(int argc, char* argv[]) {
cout.setf(ios::fixed);
cout.precision(6);
RandomNumber random;
random.setSeed(argc);
srand((unsigned) time(NULL));
cout << "---------------------------------" << endl;
cout << " Monte Carlo Pi Approximation" << endl;
cout << "---------------------------------" << endl;
cout << " Enter number of points: ";
long int k1;
cin >> k1;
cout << "Select generator number: ";
int method;
cin >> method;
random.chooseMethod(method);
cout << "---------------------------------" << endl;
long int k2 = 0;
double sumX = 0;
double sumY = 0;
for (long int i = 0; i < k1; i++) {
double x = pow(-1, int(random.nextPoint() * 10) % 2)
* random.nextPoint();
double y = pow(-1, int(random.nextPoint() * 10) % 2)
* random.nextPoint();
sumX += x;
sumY += y;
if ((pow(x, 2) + pow(y, 2)) <= 1)
k2++;
}
double pi = 4 * (double(k2) / k1);
cout << "M(X) = " << setw(10) << sumX / k1 << endl; //mathematical expectation of x
cout << "M(Y) = " << setw(10) << sumY / k1 << endl; //mathematical expectation of y
cout << endl << "Pi = " << pi << endl << endl; //approximate Pi
return 0;
}
The second method returns 4.000 consistently on my lab machine, yet returns a rather close approximation on my personal machine.
For one thing, the BBS generator as you're using it will always return 1.
Since your program takes no arguments, presumably its argc will be 1. You pass argc as the seed (why?), so the initial value of x is 1.
BBS() has the following logic:
x = (long int) (pow(x, 2)) % M;
Clearly, 1 squared modulo M gives 1, so x never changes.
When you run the simulation with such a generator, your program will always output 4.
P.S. Wikipedia has the following to say about the initial value x0 for Blum Blum Shub:
The seed x0 should be an integer that's co-prime to M (i.e. p and q are not factors of x0) and not 1 or 0.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Vastly different output C++ monte carlo approximation
On my 64-bit ubuntu computer, the following code works as expected, and returns a close approximation for pi with both algorithms. However, on the lab machine, where I must demo the code, a 32-bit rhel 3 machine, the second algorithm always returns 4, and I cannot figure out why. Any insight would be appreciated.
/*
* RandomNumber.h
*
*
*
*/
#ifndef RANDOMNUMBER_H_
#define RANDOMNUMBER_H_
class RandomNumber {
public:
RandomNumber() {
x = time(NULL);
m = pow(2, 31); //some constant value
M = 65915 * 7915; //multiply of some simple numbers p and q
method = 1;
}
RandomNumber(int seed) {
x = ((seed > 0) ? seed : time(NULL));
m = pow(2, 31); //some constant value
method = 1; //method number
M = 6543 * 7915; //multiply of some simple numbers p and q
}
void setSeed(long int seed) {
x = seed; //set start value
}
void chooseMethod(int method) {
this->method = ((method > 0 && method <= 2) ? method : 1); //choose one of two method
}
long int linearCongruential() { //first generator, that uses linear congruential method
long int c = 0; // some constant
long int a = 69069; //some constant
x = (a * x + c) % m; //solution next value
return x;
}
long int BBS() { //algorithm Blum - Blum - Shub
x = (long int) (pow(x, 2)) % M;
return x;
}
double nextPoint() { //return random number in range (-1;1)
double point;
if (method == 1) //use first method
point = linearCongruential() / double(m);
else
point = BBS() / double(M);
return point;
}
private:
long int x; //current value
long int m; // some range for first method
long int M; //some range for second method
int method; //method number
};
#endif /* RANDOMNUMBER_H_ */
And the test class:
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <iomanip>
#include "RandomNumber.h"
using namespace std;
int main() {
cout.setf(ios::fixed);
cout.precision(6);
RandomNumber random;
srand((unsigned) time(NULL));
cout << "---------------------------------" << endl;
cout << " Monte Carlo Pi Approximation" << endl;
cout << "---------------------------------" << endl;
cout << " Enter number of points: ";
long int k1;
cin >> k1;
cout << "Select generator number: ";
int method;
cin >> method;
random.chooseMethod(method);
cout << "---------------------------------" << endl;
long int k2 = 0;
double sumX = 0;
double sumY = 0;
for (long int i = 0; i < k1; i++) {
double x = pow(-1, int(random.nextPoint() * 10) % 2)
* random.nextPoint();
double y = pow(-1, int(random.nextPoint() * 10) % 2)
* random.nextPoint();
sumX += x;
sumY += y;
if ((pow(x, 2) + pow(y, 2)) <= 1)
k2++;
}
double pi = 4 * (double(k2) / k1);
cout << "M(X) = " << setw(10) << sumX / k1 << endl; //mathematical expectation of x
cout << "M(Y) = " << setw(10) << sumY / k1 << endl; //mathematical expectation of y
cout << endl << "Pi = " << pi << endl << endl; //approximate Pi
return 0;
}
The problem is that pow returns a double, which loses precision at the low end. Converting to long int for the % operator always returns the same result, and so your RNG outputs constant -60614748.
x = time(0) 1354284781
pow(x, 2) 1.83409e+18 0x1.973fdc9dc7787p+60
(long int) pow(x, 2) -2147483648 0x80000000
(long int) pow(x, 2) % M -60614748
The fix is to change x = (long int) (pow(x, 2)) % M; to x = x * x % M, performing all arithmetic within long int. Note that this is still strictly speaking incorrect, as signed overflow is undefined; more correct is to use unsigned long.
The truncation to long in BBS() causes the same "random" number to be generated.
PS. The return from the pow function is a number, which is too big to be represented in your machine's long type. When doing the conversion to long this results in undefined behaviour. One particular effect of the undefined behaviour might be the result of the conversion to be 0x80000000 or 0x7fffffff so you end up with a sequence of the same numbers.
x = time(0) 1354284781
pow(x, 2) 1.83409e+18 0x1.973fdc9dc7787p+60
A 32-bit int holds a value up to 2^31-1 the value of x^2 is greater than that.
I need to generate 4 random numbers, each between [-45 +45] degrees. and if rand%2 = 0 then I want the result (the random number generated to be equal to -angle). Once the 4 random numbers are generated it is requires to scan these angles and find a lock (the point at which the angles meet). Also -3,-2,-1,... +3 in the loop in if statement indicate that the lock takes place within 6 degrees beamwidth. the code works. But can it be simplified? also The objective is to establish a lock between 2 points by scannin elevation and azimuth angles at both points.
#include <iostream>
#include <conio.h>
#include <time.h>
using namespace std;
class Cscan
{
public:
int gran, lockaz, lockel;
};
int main()
{
srand (time(NULL));
int az1, az2, el1, el2, j, k;
BS1.lockaz = rand() % 46;
BS1.lockel = rand() % 46;
BS2.lockaz = rand() % 46;
BS2.lockel = rand() % 46;
k = rand() % 2;
if(k == 0)
k = -1;
BS1.lockaz = k*BS1.lockaz;
k = rand() % 2;
if(k == 0)
k = -1;
BS1.lockel = k*BS1.lockel;
k = rand() % 2;
if(k == 0)
k = -1;
BS2.lockaz = k*BS2.lockaz;
k = rand() % 2;
if(k == 0)
k = -1;
BS2.lockel = k*BS2.lockel;
for(az1=-45; az1<=45; az1=az1+4)
{
for(el1=-45; el1<=45; el1=el1+4)
{
for(az2=-45; az2<=45; az2=az2+4)
{
for(el2=-45; el2<=45; el2=el2+4)
{
if((az1==BS1.lockaz-3||az1==BS1.lockaz-2||az1==BS1.lockaz-1||az1==BS1.lockaz||az1==BS1.lockaz+1||az1==BS1.lockaz+2||az1==BS1.lockaz+3)&&
(az2==BS2.lockaz-3||az2==BS2.lockaz-2||az2==BS2.lockaz-1||az2==BS2.lockaz||az2==BS2.lockaz+1||az2==BS2.lockaz+2||az2==BS2.lockaz+3)&&
(el1==BS1.lockel-3||el1==BS1.lockel-2||el1==BS1.lockel-1||el1==BS1.lockel||el1==BS1.lockel+1||el1==BS1.lockel+2||el1==BS1.lockel+3)&&
(el2==BS2.lockel-3||el2==BS2.lockel-2||el2==BS2.lockel-1||el2==BS2.lockel||el2==BS2.lockel+1||el2==BS2.lockel+2||el2==BS2.lockel+3))
{
cout << "locked \n" << BS1.lockaz << " " << BS1.lockel << " " << BS2.lockaz << " " << BS2.lockel <<endl
< az1 << " " << el1 << " " << az2 << " " << el2 << endl;
k = 1;
break;
}
if(k==1)
break;
}
if(k==1)
break;
}
if(k==1)
break;
}
if(k==1)
break;
}
_getch();
}
BS1.lockaz = rand() % 91 - 45;
BS1.lockel = rand() % 91 - 45;
BS2.lockaz = rand() % 91 - 45;
BS2.lockel = rand() % 91 - 45;
Integer angles in degrees? Very questionable. Something "physical" like an angle is normally best expressed as a floating-point number, so I'd first change
typedef double angle;
struct Cscan { // why class? This is clearly POD
int gran; //I don't know what gran is. Perhaps this should also be floating-point.
angle lockaz, lockel;
};
That seems to make it more difficult at first sight because neither the random-range-selection with % works anymore nor is it much use to compare floats for equality. Which is, however, a good thing, because all of this is in fact very bad practise.
If you want to keep using rand() as the random number generator (though I'd suggest std::uniform_real_distribution), write a function to do this:
const double pi = 3.141592653589793; // Let's use radians internally, not degrees.
const angle rightangle = pi/2.; // It's much handier for real calculations.
inline angle deg2rad(angle dg) {return dg * rightangle / 90.;}
angle random_in_sym_rightangle() {
return rightangle * ( ((double) rand()) / ((double) RAND_MAX) - .5 );
}
Now you'd just do
BS1.lockaz = random_in_sym_rightangle();
BS1.lockel = random_in_sym_rightangle();
BS2.lockaz = random_in_sym_rightangle();
BS2.lockel = random_in_sym_rightangle();
Then you need to do this range-checking. That's again something to put in a dedicated function
bool equal_in_margin(angle theta, angle phi, angle margin) {
return (theta > phi-margin && theta < phi+margin);
}
Then you do this exhaustive search for locks. This could definitely be done more efficiently, but that's an algorithm issue and has nothing to do with the language. Sticking to the for loops, you can still make them look much nicer by avoiding this explicit break checking. One way is good old goto, I'd propose here you just stick it in an extra function and return when you're done
#define TRAVERSE_SYM_RIGHTANGLE(phi) \
for ( angle phi = -pi/4.; phi < pi/4.; phi += deg2rad(4) )
int lock_k // better give this a more descriptive name
( const Cscan& BS1, const Cscan& BS2, int k ) {
TRAVERSE_SYM_RIGHTANGLE(az1) {
TRAVERSE_SYM_RIGHTANGLE(el1) {
TRAVERSE_SYM_RIGHTANGLE(az2) {
TRAVERSE_SYM_RIGHTANGLE(el2) {
if( equal_in_margin( az1, BS1.lockaz, deg2rad(6.) )
&& equal_in_margin( el1, BS1.lockel, deg2rad(6.) )
&& equal_in_margin( az2, BS1.lockaz, deg2rad(6.) )
&& equal_in_margin( el2, BS2.lockel, deg2rad(6.) ) ) {
std::cout << "locked \n" << BS1.lockaz << " " << BS1.lockel << " " << BS2.lockaz << " " << BS2.lockel << '\n'
<< az1 << " " << el1 << " " << az2 << " " << el2 << std::endl;
return 1;
}
}
}
}
}
return k;
}