A while ago I implemented a Polynom approximation for a game I programmed.
I am using Newton's pyramide method.
It took me quite a while to figure it out, but my solution requires to calculate the binomial coefficients and I also have to sum up all the coefficients for the final coefficient of each power (since solving this problem is similar to squaring, cubing.. terms and calculating the binomial coefficients)
For example:
pick k out of n of the bionomeal terms and add them
one pick is multiplied
a*(x+b)(x+c)(x+d) ==> a*x^3 + a*x^2*(b+c+d) + a*x(bc+bd+cd) +a*b*c*d
so b*c*d would be one pick b*c and b*d too
My question now is:
Is there a way calculating the Polynominterpolation with the newton scheme without having to calculate all the bionomial coefficients?
My code:
https://github.com/superphil0/Polynominterpolation/blob/master/PolynomInterpolation.java
It works pretty good, although if one gives too many points it will be rather slow
because of the selection of terms which have all be summed up
(I am really bad at explaining this in english, I hope someone can understand what I want to know though)
cheers
Judging from this description, I take it that your “pyramid scheme” generates coefficients ci such that the polynomial p(x) can be written as
p(x) =
c0 + (x ‒ x0)(
c1 + (x ‒ x1)(
c2 + (x ‒ x2)(
c3 + (x ‒ x3)(
… (
cn-1 + (x ‒ xn‒1)
cn ) … ))))
Now you can compute canonical coefficients recursively from the back. Start with
pn = cn
In every step, the current polynomial can be written as
pk =
ck + (x ‒ xk)pk+1 =
ck + (x ‒ xk)(b0 +
b1x + b2x2 + …)
assuming that the next smaller polynomial has already been turned into canonical coefficients.
Now you can compute the coefficients ai of pk using those coefficients bi of pk+1. In a strict formal way, I'd have to use indices instead of a and b, but I believe that it's clearer this way. So what are the canonical coefficients of the next polynomial?
a0 = ck − xkb0
a1 = b0 − xkb1
a2 = b1 − xkb2
…
You can write this in a loop, using and reusing a single array a to hold the coefficients:
double[] a = new double[n + 1]; // initialized to zeros
for (int k = n; k >= 0; --k) {
for (int i = n - k; i > 0; --i)
a[i] = a[i - 1] - x[k]*a[i];
a[0] = c[k] - x[k]*a[0];
}
Related
double expRecursive(double x, int n) {
if (n <= 4) {
return expIterativ(x, n);
}
return expRecursive(x, n/2) *
expRecursive(x, (n + 1)/2);
}
So the problem I am dealing with is how I can write the time complexity of this method using a big O notation.
Here is what I've done so far. I'm not sure if it is correct but let me explain it. I get that T(n)= 2 T(n/2) + 1 for n>4 since we have 2 recursive calls and other operations. But when it comes to n<=4, that is where I got stuck. There is a recursive call which means that even it will be something like T(n)= T(n/2)+1. But this doesn't even feel right, I would really appreciate it if someone could help me.
Assuming a constant x for our purposes (i.e., we are not interested in the growth rate as a function of x), expIterative is also just a function of n, and is only called for cases where n <= 4. There is some largest time t* that expIterative takes to run on x and n where n goes from 0 to 4. We can simply use that largest time t* as a constant, since the range of n that can be sent as an input is bounded.
double expRecursive(double x, int n) {
if (n <= 4) { // a+b
return expIterativ(x, n); // c+t*
}
return expRecursive(x, n/2) * // c+T(n/2)
expRecursive(x, (n + 1)/2); // d+T((n+1)/2)
}
As you pointed out, we can make the simplifying assumption that n is even and just worry about that case. If we assume n is a power of 2, even easier, since then all recursive calls will be for even numbers.
We get
T(n) <= 2T(n/2) + (a+b+2c+d+t*)
The stuff in parentheses at the end is just a sum of constants, so we can add them together and call the result k:
T(n) <= 2T(n/2) + k
We can write out some terms here:
n T(n)
4 t*
8 2t* + k
16 4t* + 2k + k
32 8t* + 4k + 2k + k
...
2^n 2^(n-2)t* + 2^(n-2)k - k
= (2^n)(t* + k)/4 - k
So for an input 2^n, it takes time proportional to 2^n. That means that T(n) = O(n).
What is Cardano Triplet ?
If a set of any three positive integers, let's say a, b and c satisfies the condition
cbrt(a + b(sqrt(c)) + cbrt(a - b(sqrt(c)) == 1
Explanation.
if sum of Cubic Root of a + (b * square root of c) and Cubic root of a - (b * square root of c) equals 1 then (a, b, c) is said to be a Cardano triplet.
cbrt represents Cubic Root and sqrt means Square Root.
A integer n will be given, so the numbers a, b and c that we take when added should be lesser than or equal to n.
In short a + b + c <= n.
Constraint : n <= 2^31 -1.
Problem
I've already done something which finds out the correct triplets but when the value of n is greater than 1000 the program runs forever.
public static void cardanoTriplets(long n) {
DecimalFormat decimalFormat = new DecimalFormat("#.###");
long numberOfPairs = 0;
for (long a = 0; a <= n; a++) {
for (long b = 0; b <= n; b++) {
for (long c = 0; c <= (n - a - b); c++) {
if ((a + b + c) == n) {
double val = b * Math.sqrt(c);
double LHS = Double.parseDouble(decimalFormat.format(Math.cbrt(a + val)));
double RHS = Double.parseDouble(decimalFormat.format(Math.cbrt(a - val)));
double addedVal = LHS + RHS;
//System.out.println("RHS and LHS -: ( " + RHS + " , " + LHS + " )");
if (addedVal == 1.0d) {
numberOfPairs++;
//System.out.println(a);
//System.out.println(b);
//System.out.println(c + "\n");
}
}
}
}
}
System.out.println(numberOfPairs);
}
Results
When I pass the value of n as 8, on average the time taken to find the cardano triplet is 31ms and sometimes as low as 16ms. The result was accurate and the result is just one and the triplet is (2, 1, 5).
But when I pass the value of n as 1000, it increases to about 1015ms and the result are not as accurate. It misses out almost 19 triplets. Total number of triplets are 149 for n == 1000.
When the value of n > 1000, let's say 5000, it took 29271ms which is 29 seconds approx and the triplets found are 3364.
Is there any way to reduce time taken to a reasonable amount like less than 5 seconds ?
If so how ?
My Device Specs :
Processor : AMD Ryzen 5 3500U Quad Core
RAM : 8 GB
IDE used : IntelliJ IDEA v2021.2.3 (Community Edition)
Thank you :)
This is a number-theoretical problem; using an imprecise floating point is obviously wrong.
The correct solution requires some math insight. Cardano's name is a great hint.
The expression
cbrt(a + b(sqrt(c)) + cbrt(a - b(sqrt(c))
describes a root of a certain cubic equation. Specifically, the roots of an equation
x^3 + px - q = 0
are
cbrt(q/2 + sqrt((q/2)^2 + (p/3)^3)) + cbrt(q/2) - sqrt(q/2)^2 + (p/3)^3))
Comparing with your problem statement, conclude that a = q/2, and c*b^2 = (q/2)^2 + (p/3)^3
Since a is an integer, q must be even, and since b, c are also integers, p must be divisible by 3. Therefore we are interested in the equations
x^3 + 3ux - 2a = 0
having 1 as a root. That narrows the problem down to searching u, v such that 1 + 3u - 2a = 0. Here u^3 + a^2 = b^2*c. Notice that u must be odd.
All these observations lead to a (pseudo)code:
for u in range(1, n, 2)
a = (1 + 3u)/2
t = u^3 + a^2
find the largest b such that b^2 divides t
c = t / b^2
if a + b + c < n
they are a Cardano triplet
Your first problem, is the loop-in-loop-in-loop what will take 1.000.000.000 rounds for n=1000.
As you know already that n = a + b + c, you can take one loop out. the c-loop
and rewrite as:
for (long a = 0; a <= n; a++) {
for (long b = 0; b <= (n - a); b++) {
long c = n - a - b;
so you go from n * n * n -> n * n
If the equation is n => a + b + c (as in your problem statement), you can use:
for (long a = 0; a <= n; a++) {
for (long b = 0; b <= (n - a); b++) {
for (long c = 0; c <= (n - a - b); c++) {
Second, you are doing a format to a decimal and then convert back to double where as the Math.cbrt gives already a double. I would suggest not doing so.
The problem of "missing 19 triplets" is related to the point above. You only accept 1.0d as the correct answer, there in the previous step you did formatting on the doubles (most likely giving rounding issues). Even if you would take out the formatting, I believe it is better to allow for a bit more rounding error..
something like:
if (0.999 < addedVal && addedVal < 1.001)
However, I have no idea on the math of this equation as there must be a reason why you say there are 149 triplets.. Depending on the rounding for sure you have different answers... I believe there is something like mathemathical proof the triplets are 1.
Last what you can do: I believe the calculation of the Math.cbrt is not that fast. You are repeating this a lot. You can keep track of your calculation by placing the result of the Math,cbrt in a HashSet. The Key is the input and the Value the result of the Math.cbrt.
So first check if you have the Key already in the HashSet, if not calculate the cbrt and place it, if already available us it..
I am trying to solve a problem that I need to get value of three unknowns(x,y,z) knowing some info. their summation is equal to 70, x^2 + y^2 = z^2 and x < y < z.
Answer should be x = 20, y = 21, z = 29
I tried to solve it as two equations in three unknowns but I failed. Any hints to get the solution ? I want to find an algorithm or equation to build a java code that solve this problem
I'll assume that x, y, and z must be positive integers, since removing the integers restriction allows infinitely many solutions. Here is an algorithm--I'll leave the code to you.
Your second equation x^2 + y^2 = z^2 means that x, y, and z form a Pythagorean triple. All solutions to that equation have the form
x = k(m^2 - n^2), y = 2kmn, z = k(m^2 + n^2)
(with possibly x and y swapped) where m, n, and k are positive integers, m > n, one of m and n is even and the other is odd, and (m, n) are relatively prime. You can drop those last two restrictions on m and n, which is to make the triples have unique representation.
Your third limitation x < y < z merely makes a unique triple from the three values. Importantly, your first restriction x + y + z = 70 means that your solution has "small" values.
So in your code, vary the three parameters k, m, and n. There are only finitely many values that allow the sum of x, y, and z to be less than or equal 70, which places limits on k, m, and n. Find the ones that equal make the sum of x, y, and z to be 70. You can cut the number of trials in half by not letting m and n be both even or both odd. You can also avoid explicitly varying k by varying only m and n and calculating what k should be, since each of x, y, z vary proportionally with k, and accept only integral k.
This is somewhat of a brute-force solution, but it is easy to program and will be faster than just trying all values of x, y, and z.
EDIT: I now see that x, y, and z may also be zero. That theoretically means that you need to test for x = 0, but that is clearly impossible here since then y^2 = z^2 which contradicts y < z. So no change is needed to my algorithm.
Expanding on #RoryDaulton's answer, taking x = k(m^2 - n^2), y = 2kmn and z = k(m^2 + n^2) and applying the sum constraint gives us
2*k*m*(m + n) = 70
Or
k * m * (m + n) = 35 = 7 * 5 = 35 * 1
The important thing to note is that the RHS of the above has only two unique factors; the LHS has three. Thus at least one factor of the LHS (k, m, m + n) must be 1.
Since m and n are unique positive integers, m + n will always be greater than 1. Thus,
k = 1 or m = 1
And the only possible values for the remaining LHS factors are 7 and 5 or 35 and 1.
This makes the problem much easier to brute force.
I have solved the question and I want to thank all people who helped me.
This is My code to solve the problem
int x,y,z;
long mul=0;
for(int n=1;n<=sum;n++){
for (int m=2;m<=sum;m++){
x= (int) ((Math.pow(m,2)) - (Math.pow(n,2)));
y= 2*m*n;
z= (int) ((Math.pow(m,2)) + (Math.pow(n,2)));
if(x+y+z == sum){
mul = x*z*y;
}
}}
return mul; }}
I'm currently working on Java for Android. I try to implement the FFT in order to realize a kind of viewer of the frequencies.
Actually I was able to do it, but the display is not fluid at all.
I added some traces in order to check the treatment time of each part of my code, and the fact is that the FFT takes about 300ms to be applied on my complex array, that owns 4096 elements. And I need it to take less than 100ms, as my thread (that displays the frequencies) is refreshed every 100ms. I reduced the initial array in order that the FFT results own only 1028 elements, and it works, but the result is deprecated.
Does someone have an idea ?
I used the default fft.java and Complex.java classes that can be found on the internet.
For information, my code computing the FFT is the following :
int bytesPerSample = 2;
Complex[] x = new Complex[bufferSize/2] ;
for (int index = 0 ; index < bufferReadResult - bytesPerSample + 1; index += bytesPerSample)
{
// 16BITS = 2BYTES
float asFloat = Float.intBitsToFloat(asInt);
double sample = 0;
for (int b = 0; b < bytesPerSample; b++) {
int v = buffer[index + b];
if (b < bytesPerSample - 1 || bytesPerSample == 1) {
v &= 0xFF;
}
sample += v << (b * 8);
}
double sample32 = 100 * (sample / 32768.0); // don't know the use of this compute...
x[index/bytesPerSample] = new Complex(sample32, 0);
}
Complex[] tx = new Complex[1024]; // size = 2048
///// reduction of the size of the signal in order to improve the fft traitment time
for (int i = 0; i < x.length/4; i++)
{
tx[i] = new Complex(x[i*4].re(), 0);
}
// Signal retrieval thanks to the FFT
fftRes = FFT.fft(tx);
I don't know Java, but you're way of converting between your input data and an array of complex values seems very convoluted. You're building two arrays of complex data where only one is necessary.
Also it smells like your complex real and imaginary values are doubles. That's way over the top for what you need, and ARMs are veeeery slow at double arithmetic anyway. Is there a complex class based on single precision floats?
Thirdly you're performing a complex fft on real data by filling the imaginary part of your complexes with zero. Whilst the result will be correct it is twice as much work straight off (unless the routine is clever enough to spot that, which I doubt). If possible perform a real fft on your data and save half your time.
And then as Simon says there's the whole issue of avoiding garbage collection and memory allocation.
Also it looks like your FFT has no preparatory step. This mean that the routine FFT.fft() is calculating the complex exponentials every time. The longest part of the FFT calculation is working out the complex exponentials, which is a shame because for any given FFT length the exponentials are constants. They don't depend on your input data at all. In the real time world we use FFT routines where we calculate the exponentials once at the start of the program and then the actual fft itself takes that const array as one of its inputs. Don't know if your FFT class can do something similar.
If you do end up going to something like FFTW then you're going to have to get used to calling C code from your Java. Also make sure you get a version that supports (I think) NEON, ARM's answer to SSE, AVX and Altivec. It's worth ploughing through their release notes to check. Also I strongly suspect that FFTW will only be able to offer a significant speed up if you ask it to perform an FFT on single precision floats, not doubles.
Google luck!
--Edit--
I meant of course 'good luck'. Give me a real keyboard quick, these touchscreen ones are unreliable...
First, thanks for all your answers.
I followed them and made two test :
first one, I replace the double used in my Complex class by float. The result is just a bit better, but not enough.
then I've rewroten the fft method in order not to use Complex anymore, but a two-dimensional float array instead. For each row of this array, the first column contains the real part, and the second one the imaginary part.
I also changed my code in order to instanciate the float array only once, on the onCreate method.
And the result... is worst !! Now it takes a little bit more than 500ms instead of 300ms.
I don't know what to do now.
You can find below the initial fft fonction, and then the one I've re-wroten.
Thanks for your help.
// compute the FFT of x[], assuming its length is a power of 2
public static Complex[] fft(Complex[] x) {
int N = x.length;
// base case
if (N == 1) return new Complex[] { x[0] };
// radix 2 Cooley-Tukey FFT
if (N % 2 != 0) { throw new RuntimeException("N is not a power of 2 : " + N); }
// fft of even terms
Complex[] even = new Complex[N/2];
for (int k = 0; k < N/2; k++) {
even[k] = x[2*k];
}
Complex[] q = fft(even);
// fft of odd terms
Complex[] odd = even; // reuse the array
for (int k = 0; k < N/2; k++) {
odd[k] = x[2*k + 1];
}
Complex[] r = fft(odd);
// combine
Complex[] y = new Complex[N];
for (int k = 0; k < N/2; k++) {
double kth = -2 * k * Math.PI / N;
Complex wk = new Complex(Math.cos(kth), Math.sin(kth));
y[k] = q[k].plus(wk.times(r[k]));
y[k + N/2] = q[k].minus(wk.times(r[k]));
}
return y;
}
public static float[][] fftf(float[][] x) {
/**
* x[][0] = real part
* x[][1] = imaginary part
*/
int N = x.length;
// base case
if (N == 1) return new float[][] { x[0] };
// radix 2 Cooley-Tukey FFT
if (N % 2 != 0) { throw new RuntimeException("N is not a power of 2 : " + N); }
// fft of even terms
float[][] even = new float[N/2][2];
for (int k = 0; k < N/2; k++) {
even[k] = x[2*k];
}
float[][] q = fftf(even);
// fft of odd terms
float[][] odd = even; // reuse the array
for (int k = 0; k < N/2; k++) {
odd[k] = x[2*k + 1];
}
float[][] r = fftf(odd);
// combine
float[][] y = new float[N][2];
double kth, wkcos, wksin ;
for (int k = 0; k < N/2; k++) {
kth = -2 * k * Math.PI / N;
//Complex wk = new Complex(Math.cos(kth), Math.sin(kth));
wkcos = Math.cos(kth) ; // real part
wksin = Math.sin(kth) ; // imaginary part
// y[k] = q[k].plus(wk.times(r[k]));
y[k][0] = (float) (q[k][0] + wkcos * r[k][0] - wksin * r[k][1]);
y[k][1] = (float) (q[k][1] + wkcos * r[k][1] + wksin * r[k][0]);
// y[k + N/2] = q[k].minus(wk.times(r[k]));
y[k + N/2][0] = (float) (q[k][0] - (wkcos * r[k][0] - wksin * r[k][1]));
y[k + N/2][1] = (float) (q[k][1] - (wkcos * r[k][1] + wksin * r[k][0]));
}
return y;
}
actually I think I don't understand everything.
First, about Math.cos and Math.sin : how do you want me not to compute it each time ? Do you mean that I should instanciate the whole values only once (e.g store it in an array) and use them for each compute ?
Second, about the N % 2, indeed it's not very useful, I could make the test before the call of the function.
Third, about Simon's advice : I mixed what he said and what you said, that's why I've replaced the Complex by a two-dimensional float[][]. If that was not what he suggested, then what was it ?
At least, I'm not a FFT expert, so what do you mean by making a "real FFT" ? Do you mean that my imaginary part is useless ? If so, I'm not sure, because later in my code, I compute the magnitude of each frequence, so sqrt(real[i]*real[i] + imag[i]*imag[i]). And I think that my imaginary part is not equal to zero...
thanks !
I am looking to implement the simple equation:
i,j = -Q ± √(Q2-4PR) / 2P
To do so I have the following code (note: P = 10. Q = 7. R = 10):
//Q*Q – 4PR = -351 mod 11 = -10 mod 11 = 1, √1 = 1
double test = Math.sqrt(modulo(((Q*Q) - ((4*P)*R))));
// Works, but why *-10 needed?
i = (int)(((-Q+test)/(P*2))*-10); // i = 3
j = (int)(((-Q-test)/(P*2))*-10); // j = 4
To put it simply, test takes the first part of the equation and mods it to a non-zero integer in-between 0 and 11, then i and j are written. i and j return the right number, but for some reason *-10 is needed to get them right (a number I guessed to get the correct values).
If possible, I'd like to find a better way of performing the above equation because my way of doing it seems wrong and just works. I'd like to do it as the equation suggests, rather than hack it to work.
The quadratic equation is more usually expressed in terms of a, b and c. To satisfy ax2+bx+c = 0, you get (-b +/- sqrt(b^2-4ac)) / 2a as answers.
I think your basic problem is that you're using modulo for some reason instead of taking the square root. The factor of -10 is just a fudge factor which happens to work for your test case.
You should have something like this:
public static void findRoots(double a, double b, double c)
{
if (b * b < 4 * a * c)
{
throw new IllegalArgumentException("Equation has no roots");
}
double tmp = Math.sqrt(b * b - 4 * a * c);
double firstRoot = (-b + tmp) / (2 * a);
double secondRoot = (-b - tmp) / (2 * a);
System.out.println("Roots: " + firstRoot + ", " + secondRoot);
}
EDIT: Your modulo method is currently going to recurse pretty chronically. Try this instead:
public static int modulo(int x)
{
return ((x % 11) + 11) % 11;
}
Basically the result of the first % 11 will be in the range [-10, 10] - so after adding another 11 and taking % 11 again, it'll be correct. No need to recurse.
At that point there's not much reason to have it as a separate method, so you can use:
public static void findRoots(double a, double b, double c)
{
int squareMod11 = (((b * b - 4 * a * c) % 11) + 11) % 11;
double tmp = Math.sqrt(squareMod11);
double firstRoot = (-b + tmp) / (2 * a);
double secondRoot = (-b - tmp) / (2 * a);
System.out.println("Roots: " + firstRoot + ", " + secondRoot);
}
You need to take the square root. Note that Q^2-4PR yields a negative number, and consequently you're going to have to handle complex numbers (or restrict input to avoid this scenario). Apache Math may help you here.
use Math.sqrt for the square root. Why do you cast i and j to ints? It is equation giving you roots of square function, so i and j can be any complex numbers. You shall limit the discriminant to positive-only values for real (double) roots, otherwise use complex numbers.
double test = Q*Q - 4*P*R;
if(Q < 0) throw new Exception("negative discriminant!");
else {
test = Math.sqrt(test);
double i = (-Q + test) / 2*P;
double i = (-Q - test) / 2*P;
}
Why are you doing modulo and not square root? Your code seems to be the way to get the roots of a quadratic equation ((a±sqrt(b^2-4ac))/2a), so the code should be:
double delta = Q*Q-4*P*R);
if(delta < 0.0) {
throw new Exception("no roots");
}
double d = Math.power(delta,0.5);
double r1 = (Q + d)/(2*P)
double r2 = (Q - d)/(2*P)
As pointed out by others, your use of mod isn't even wrong. Why are you making up mathematics like this?
It's well known that the naive solution to the quadratic equation can have problems if the value of b is very nearly equal to the discriminant.
A better way to do it is suggested in section 5.6 of "Numerical Recipes in C++": if we define
(source: equationsheet.com)
Then the two roots are:
and
Your code also needs to account for pathological cases (e.g., a = 0).
Let's substitute your values into these formulas and see what we get. If a = 10, b = 7, and c = 10, then :
(source: equationsheet.com)
Then the two roots are:
(source: equationsheet.com)
and
(source: equationsheet.com)
I think I have the signs right.
If your calculation is giving you trouble, it's likely due to the fact that you have complex roots that your method can't take into account properly. You'll need a complex number class.