Finding roots but not asymptotes of a function - c++

I writing a program to numerically find the roots of functions with irrational roots by various methods.
For methods such as linear interpolation, you need to find the approximate range in which a root lies, for this I wrote this code:
bool fxn1 = false;
bool fxn2 = false;
vector<float> root_list;
if(f_x(-100) < 0)
{
fxn2 = true;
}
for(float i = -99.99; i < 100.01; i += 0.01)
{
fxn1 = fxn2;
if(f_x(i) < 0)
{
fxn2 = true;
}
else
{
fxn2 = false;
}
if((fxn1 == false && fxn2 == true) || (fxn1 == true && fxn2 == false))
{
root_list.push_back(i-0.01);
root_list.push_back(i);
}
}
However, for non-continuous functions (i.e. functions with asymptotes), this code will also be triggered when the function swaps from positive to negative values either side of the asymptote.
Is there a way to get the program to tell the difference between a root and an asymptote?
Thanks in advance

If the function, f(x), is converging on a point inside [a,b] then the half-way point (a + b) / 2 should be closer to zero than a or b.
This observation leads to the following procedure:
Let mid = (a + b) / 2
If |f(mid)| < |f(a)| AND |f(mid)| < |f(b)| Then
Algorithm has converged to a root
Else
Algorithm has converged to an asymptote
End
In this pseudo code |.| denotes floating-point absolute value.

Finding numerically a root only make sense if the function has nice properties, and at least is continuous. What would you think about this one:
f: x -> f(x) defined by:
2 * i < x < 2 * i + 1 (i element of Z) : f(x) = x
2 - i + 1 < x < 2 * i (i element of Z) : f(x) = -x
x = i (i element of Z) : f(x) = 1
It is perfectly defined on R, is bounded on any bounded interval, has positive and negative values on any interval of size > 1, and is continuous on any non integer point, but it has no root.
It is simply because the rule that a root must exist on segment ]x, y[ if x < 0 < y or y < 0 < x only applies if the function is continuous on the interval.
And good luck if you want to numerically test for continuity of a function...

Related

Fast way of finding all numbers X that sum with themselves with one digit removed to get N?

I'm working on an assignment that gives an integer N and tasks us to find all possible combinations of X, Y such that X + Y = N and Y = X with one digit removed. For example, 302 would have the following solutions:
251 + 51 = 302
275 + 27 = 302
276 + 26 = 302
281 + 21 = 302
301 + 01 = 302
My code to accomplish this can find all of the correct answers, but it runs too slowly for very large numbers (it takes roughly 8 seconds for the largest possible number, 10^9, when I would like for the entire algorithm of up to 100 of these cases to complete in under 3 seconds).
Here's some code describing my current solution:
//Only need to consider cases where x > y.
for(int x = n * 0.5; x <= n; x++)
{
//Only considers cases where y's rightmost digit could align with x.
int y = n - x,
y_rightmost = y % 10;
if(y_rightmost == x % 10 || y_rightmost == (x % 100) / 10)
{
//Determines the number of digits in x and y without division. places[] = {1, 10, 100, 1000, ... 1000000000}
int x_numDigits = 0,
y_numDigits = 0;
while(x >= places[x_numDigits])
{
if(y >= places[x_numDigits])
y_numDigits++;
x_numDigits++;
}
//y must have less digits than x to be a possible solution.
if(y_numDigits < x_numDigits)
{
if(func(x, y))
{
//x and y are a solution.
}
}
}
Where func is a function to determine if x and y only have a one digit difference. Here's my current method for calculating that:
bool func(int x, int y)
{
int diff = 0;
while(y > 0)
{
if(x % 10 != y % 10)
{
//If the rightmost digits do not match, move x to the left once and check again.
x /= 10;
diff++;
if(diff > 1)
return false;
}
else
{
//If they matched, both move to the next digit.
x /= 10;
y /= 10;
}
}
//If the last digit in x is the only difference or x is composed of 0's led by 1 number, then x, y is a solution.
if((x < 10 && diff == 0) || (x % 10 == 0))
return true;
else
return false;
}
This is the fastest solution that I've been able to find so far (other methods I tried included converting X and Y into strings and using a custom subsequence function, along with dividing X into a prefix and suffix without each digit from the right to the left and seeing if any of these summed to Y, but neither worked as quickly). However, it still doesn't scale as well as I need it to with larger numbers, and I'm struggling to think of any other ways to optimize the code or underlying mathematical reasoning. Any advice would be greatly appreciated.
Consider solving a simpler solution first:
Finding X and Y such that X + Y = N
In pseudo-code you steps should look like this:
loop through the array and with every given item do the next:
add this number to Set and check whether there is N - item
This will work as O(n) complexity for unique array.
So improve it to work with duplicated numbers by looping through an array first and adding counter of duplicates for every number. Use some kind of Dictionary for c++ or extend Set. And every time you find the necessary number check for counter.
After doing that you will just have to write this "digit check" function and apply it when finding the value in Set.

Path-finding algorithm for a game

I have this assigment in university where I'm given the code of a C++ game involving pathfinding. The pathfinding is made using a wave function and the assigment requires me to make a certain change to the way pathfinding works.
The assigment requires the pathfinding to always choose the path farthest away from any object other than clear space. Like shown here:
And here's the result I've gotten so far:
Below I've posted the part of the Update function concerning pathfinding as I'm pretty sure that's where I'll have to make a change.
for (int y = 0, o = 0; y < LEVEL_HEIGHT; y++) {
for (int x = 0; x < LEVEL_WIDTH; x++, o++) {
int nCost = !bricks[o].type;
if (nCost) {
for (int j = 0; j < 4; j++)
{
int dx = s_directions[j][0], dy = s_directions[j][1];
if ((y == 0 && dy < 0)
|| (y == LEVEL_HEIGHT - 1 && dy > 0)
|| (x == 0 && dx < 0)
|| (x == LEVEL_WIDTH - 1 && dx > 0)
|| bricks[o + dy * LEVEL_WIDTH + dx].type)
{
nCost = 2;
break;
}
}
}
pfWayCost[o] = (float)nCost;
}
}
Also here is the Wave function if needed for further clarity on the problem.
I'd be very grateful for any ideas on how to proceed, since I've been struggling with this for quite some time now.
Your problem can be reduced to a problem known as minimum-bottle-neck-spanning-tree.
For the reduction do the following:
calculate the costs for every point/cell in space as the minimal distance to an object.
make a graph were edges correspond to the points in the space and the weights of the edges are the costs calculated in the prior step. The vertices of the graph corresponds to the boundaries between cell.
For one dimensional space with 4 cells with costs 10, 20, 3, 5:
|10|20|3|5|
the graph would look like:
A--(w=10)--B--(w=20)--C--(w=3)--D--(w=5)--E
With nodes A-E corresponding to the boundaries of the cells.
run for example the Prim's algorithm to find the MST. You are looking for the direct way from the entry point (in the example above A) to the exit point (E) in the resulting tree.

gsl_histogram: Value being equal to an edge between two bins, to which bin will the value be assigned?

To which bin of a gsl_histogram is a value assigned that falls exactly on the edge between two bins?
E.g. when I call gsl_histogram_increment( h, x), with x being exactly 0 and the bin edges being -0.2, 0, 0.2, 0.4 etc. will I get an increment in the positive range(0, 0.2) or the negative range(-0.2, 0)?
EDIT: yep my ranges are uniform.
if your bin distribution is linear (as in your example) then this is the code that is being executed (taken from gsl-1.15/histogram/find.c):
/* optimize for linear case */
#ifdef LINEAR_OPT
{
double u = (x - range[0]) / (range[n] - range[0]);
i_linear = (size_t) (u * n);
}
if (x >= range[i_linear] && x < range[i_linear + 1])
{
*i = i_linear;
return 0;
}
#endif
note the >= for the lower bin edge and the < for the upper bin edge therefore your 0.0 value should drop into the 0.0 - 0.2 bin
for a non-linear bin distribution a binary search is performed, i.e.:
/* perform binary search */
upper = n ;
lower = 0 ;
while (upper - lower > 1)
{
mid = (upper + lower) / 2 ;
if (x >= range[mid])
{
lower = mid ;
}
else
{
upper = mid ;
}
}
*i = lower ;
note the usage of the >= implies that a value falling on a bin edge will be included in the 'upper' bin of the two (same as the linear case)
maybe double check by running your example and observing what bin the value is added to
gsl_histogram_increment appears to use the condition L <= x < U for deciding whether to place value x in bin (L, U). So 0 would end up in (0, 0.2).

C++ variables always coming out as zero

I'm running a simple for loop with some if statements. In this for loop, 3 variables are to be given a value depending on the index value in the for loop. It seems fairly simple, however, when I run the code, the values always come out as zero and I have no idea why this is happening. My for loop is provided below. I appreciate any suggestions.
double A [N+1];
double r;
double s;
double v;
for(int i = 2; i < N+1; i++)
{
if(i == 2)
{
r = 1/2/i/(i-1);
s = -1/2/(i*i - 1);
v = 1/4/i/(i+1);
}
else if(i <= N-2 && i > 2)
{
r = 1/4/i/(i-1);
s = -1/2/(i*i - 1);
v = 1/4/i/(i+1);
}
else if(i <= N-4 && i > N-2)
{
r = 1/4/i/(i-1);
s = 0;
v = 1/4/i/(i+1);
}
else
{
r = 1/4/i/(i-1);
s = 0;
v = 0;
}
A[i] = r*F[i-2] + s*F[i] + v*F[i+2];
cout << r << s << v << endl;
}
It’s happening because you’re using integer division. An example:
r = 1/2/i/(i-1);
This is the same as:
r = ((1 / 2) / i) / (i - 1);
Which is the same as:
r = (0 / i) / (i - 1);
… which is the same as:
r = 0 / (i - 1);
… which is 0.
Because 1 / 2 is 0 in integer arithmetic. To fix this, use floating point values.
Three things:
else if(i <= N-4 && i > N-2) makes no sense, that condition cannot hold
all your divisions are integer divisions - to fix, convert one of the numbers to a double.
as a result of 1, when i = N-1, and i = N, then the last branch is taken where you force two variables to 0 anyway!
1, 2 and 4 are integers. In integerland 1/2 = 0 and 1/4 = 0
With integers, 1/2 is zero. I would suggest (for a start) changing constants like 2 into 2.0 to ensure they're treated as doubles.
You may also want to (though it may not be necessary) cast all your i variables to floating point values as well, just for completeness, such as:
r = 1.0 / 2.0 / (double)i / ((double)i - 1.0);
The fact that r is a double in no way affects the calculations done on the right of the =. It only affects the final bit (the actual assignment).
1/2, 1/4 and -1/2 will always be zero because of the integer division.So try with 1.0/2.0, 1.0/4.0 and -1.0/2.0 to get it sorted out quickly. But follow the basics and do not use many magic numbers inside a code. Consider creating constants for them and use .

Miller-Rabin test: bug in my code

I've written a Miller-Rabin primality test based on the following pseudo code:
Input: n > 2, an odd integer to be tested for primality;
k, a parameter that determines the accuracy of the test
Output: composite if n is composite, otherwise probably prime
write n − 1 as 2s·d with d odd by factoring powers of 2 from n − 1
LOOP: repeat k times:
pick a randomly in the range [2, n − 1]
x ← ad mod n
if x = 1 or x = n − 1 then do next LOOP
for r = 1 .. s − 1
x ← x2 mod n
if x = 1 then return composite
if x = n − 1 then do next LOOP
return composite
return probably prime
The code I have rarely gets past 31 (if I put it in a loop to test numbers from 2 to 100). There must be something wrong but I can't see what it is.
bool isProbablePrime(ulong n, int k) {
if (n < 2 || n % 2 == 0)
return n == 2;
ulong d = n - 1;
ulong s = 0;
while (d % 2 == 0) {
d /= 2;
s++;
}
assert(2 ^^ s * d == n - 1);
outer:
foreach (_; 0 .. k) {
ulong a = uniform(2, n);
ulong x = (a ^^ d) % n;
if (x == 1 || x == n - 1)
continue;
foreach (__; 1 .. s) {
x = (x ^^ 2) % n;
if (x == 1) return false;
if (x == n - 1) continue outer;
}
return false;
}
return true;
}
I've also tried the variant
...
foreach (__; 1 .. s) {
x = (x ^^ 2) % n;
if (x == 1) return false;
if (x == n - 1) continue outer;
}
if ( x != n - 1) return false; // this is different
...
I have a different version of the test that works correctly but it uses modpow. I'd like to have a version that stays closer to the pseudo code that's part of the rossetta.org task description.
Edit: Re: overflow problem. I suspected something like that. I'm still puzzled why the Ruby version doesn't have that problem. It probably handles it differently under the hood.
If I use BigInt, the code does work, but becomes a lot slower than when I use modpow. So I guess I can't get away from that. It's a pity Phobos doesn't have a modpow built-in, or I must have overlooked it.
ulong x = ((BigInt(a) ^^ d) % BigInt(n)).toLong();
In this statement
ulong x = (a ^^ d) % n;
the quantity (a ^^ d) is probably overflowing before the mod operation can take place. The modpow version wouldn't suffer from this problem, since that algorithm avoids the need for arbitrarily large intermediate values.