I need an enhancement on Brute-Force polynomial evaluation algorithm. I received the highest power of x (value of n), the value of coefficients of all elements of polynomial (a, b, c, ..) as an integer array list. But I can't apply this algorithm on java: f(x) = ax^n + bx^(n-1) + cx^(n-3)+... + z How can I apply this polynomial on java? What is the algorithm for it? Any helps?
package brute.force;
import java.util.*;
import java.util.Scanner;
public class BruteForce {
public static void main(String[] args) {
Scanner scan = new Scanner (System.in);
ArrayList<Integer> coefficients = new ArrayList<>();
int powerOfX, x;
System.out.print("Enter integers please ");
System.out.println("(EOF or non-integer to terminate): ");
while(scan.hasNextInt()){
coefficients.add(scan.nextInt());
}
Integer [] nums = coefficients.toArray(new Integer[0]);
for(int i = 0; i < nums.length; i++){
System.out.println(nums[i]);
}
}
}
You need to calculate it with following iteration:
double result = 0;
Integer [] nums = coefficients.toArray(new Integer[0]);
for(int i = 0; i < nums.length; i++){
result = result *x + nums[i];
}
System.out.println(result);
It is known as Horner's method.
The benefit of this approach for example of fourth degree of polynomial is:
f(x) = ax^3 + bx^2 + cx + z
is transformed to:
f(x) = ((a)*x + b)*x + c)*x + z
You mean this?
double result = 0;
for(int i = 0; i < nums.length; i++) {
result += nums[i] * Math.pow(x, i); // nums has coefficients in increasing order
}
You can use Horner's method to calculate a polynomial in a computationally efficient form.
user987339 has posted an implementation in Java.
Related
I would like to generate an array of 100 numbers and find their average and sum. I am able to do this but I am not able to get the output of numbers into ascending order. I am super new to Java.
import java.util.Random;
public class randomNumberGen
{
public static void main(String [] args)
{
Random r=new Random();
double sum = 0; // is double so to prevent int division later on
int amount = 100;
int upperBound = 100;
for (int i = 0; i < amount; i++){
int next = r.nextInt(upperBound) + 1; // creates a random int in [1,100]
System.out.println(next);
sum += next; // accumulate sum of all random numbers
}
System.out.println("Your average is: " + (sum / amount));
System.out.println("Your sum is: " + (sum));
}
}
it is very easy. however I didn't see any array in your code. I create an example code for you. you can ask for more help.
public static void main(String[] args) {
SecureRandom random = new SecureRandom(); // it is better to use this library
double sum = 0; // is double so to prevent int division later on
int amount = 100;
int upperBound = 100;
int[] array = new int[amount]; // create an array with amount size
for (int i = 0; i < amount; i++) {
array[i] = random.nextInt(upperBound) + 1; // creates a random int in [1 , upperBound]
sum += array[i]; // accumulate sum of all random numbers
}
Arrays.sort(array); // sort array in default order which is ascending
System.out.println(Arrays.toString(array)); // toString is a way to print all of array, without iterate it and print it
System.out.println("Your average is: " + (sum / amount));
System.out.println("Your sum is: " + sum);
}
There are a lot of different sorting methods. For a beginner start with either Bubble Sort or Insertion Sort. Insertion Sort is slightly better as on average it runs slightly faster.
I offer to use one of special collections to sort numbers internally, without using one of sorting algorithms (e.g. us PriorityQueue):
public static void main(String[] args) {
final int amount = 100;
Random random = new SecureRandom();
Queue<Integer> queue = new PriorityQueue<>(amount, Comparator.naturalOrder()); // Comparator.reverseOrder() for reverse order
int sum = 0;
for (int i = 0; i < amount; i++) {
int val = random.nextInt(100) + 1;
sum += val;
queue.add(val);
}
System.out.println(Arrays.toString(queue.toArray()));
System.out.println("Your average is: " + (double)sum / amount);
System.out.println("Your sum is: " + sum);
}
I'm not sure whether this is a maths.se or a SO question, but I'm going with SO as I think it's related to my Java.
I'm following a text book on Gaussian Processes (R&W) and implementing some examples in Java. One common step for several examples is to generate a Cholesky decomposition of a covariance matrix. In my attempt I can get successful results for matrices up to a limited size (33x33). However, for anything larger a NaN appears in the diagonal (at 32,32) and so all subsequent values in the matrix are likewise NaNs.
The code is shown below, and the source of the NaN is indicated in the cholesky method. Essentially the covariance element a[32][32] is 1.0, but the value of sum is a little over this (1.0000001423291431), so the square root is imaginary. So my questions are:
Is this an expected result from linear algebra, or, e.g., an
artefact of my implementation?
How is this problem best avoided in practice?
Note that I'm not looking for recommendations of libraries to use. This is simply for my own understanding.
Apologies for the length, but I've tried to provide a complete MWE:
import static org.junit.Assert.assertFalse;
import org.junit.Test;
public class CholeskyTest {
#Test
public void testCovCholesky() {
final int n = 34; // Test passes for n<34
final double[] xData = getSpread(-5, 5, n);
double[][] cov = covarianceSE(xData);
double[][] lower = cholesky(cov);
for(int i=0; i<n; ++i) {
for(int j=0; j<n; ++j) {
assertFalse("NaN at " + i + "," + j, Double.isNaN(lower[i][j]));
}
}
}
/**
* Generate n evenly space values from min to max inclusive
*/
private static double[] getSpread(final double min, final double max, final int n) {
final double[] values = new double[n];
final double delta = (max - min)/(n - 1);
for(int i=0; i<n; ++i) {
values[i] = min + i*delta;
}
return values;
}
/**
* Calculate the covariance matrix for the given observations using
* the squared exponential (SE) covariance function.
*/
private static double[][] covarianceSE (double[] v) {
final int m = v.length;
double[][] k = new double[m][];
for(int i=0; i<m; ++i) {
double vi = v[i];
double row[] = new double[m];
for(int j=0; j<m; ++j) {
double dist = vi - v[j];
row[j] = Math.exp(-0.5*dist*dist);
}
k[i] = row;
}
return k;
}
/**
* Calculate lower triangular matrix L such that LL^T = A
* Using Cholesky decomposition from
* https://rosettacode.org/wiki/Cholesky_decomposition#Java
*/
private static double[][] cholesky(double[][] a) {
final int m = a.length;
double[][] l = new double[m][m];
for(int i = 0; i< m;i++){
for(int k = 0; k < (i+1); k++){
double sum = 0;
for(int j = 0; j < k; j++){
sum += l[i][j] * l[k][j];
}
l[i][k] = (i == k) ? Math.sqrt(a[i][i] - sum) : // Source of NaN at 32,32
(1.0 / l[k][k] * (a[i][k] - sum));
}
}
return l;
}
}
Hmm, I think I've found an answer to my own question, from the same textbook I was following. From R&W p.201:
In practice it may be necessary to add a small multiple of the
identity matrix $\epsilon I$ to the covariance matrix for numerical
reasons. This is because the eigenvalues of the matrix K can decay
very rapidly [...] and without this stabilization the Cholesky
decomposition fails. The effect on the generated samples is to add
additional independent noise of variance $epsilon$.
So the following change seems to be sufficient:
private static double[][] cholesky(double[][] a) {
final int m = a.length;
double epsilon = 0.000001; // Small extra noise value
double[][] l = new double[m][m];
for(int i = 0; i< m;i++){
for(int k = 0; k < (i+1); k++){
double sum = 0;
for(int j = 0; j < k; j++){
sum += l[i][j] * l[k][j];
}
l[i][k] = (i == k) ? Math.sqrt(a[i][i]+epsilon - sum) : // Add noise to diagonal values
(1.0 / l[k][k] * (a[i][k] - sum));
}
}
return l;
}
I just finished writing my own version of a Cholesky Decomposition routine in C++ and JavaScript. Instead of computing L, it computes U, but I would be curious to test it with the matrix that causes the NaN error. Would you be able to post the matrix here, or contact me (info in Profile.)
I'm trying to write a method that calculates the exponential of a square matrix. In this instance, the matrix is a square array of value:
[1 0]
[0 10]
and the method should return a value of:
[e 0]
[0 e^10]
However, when I run my code, I get a range of values depending on what bits I've rearranged, non particularly close to the expected value.
The way the method works is to utilise the power series for the matrix, so basically for a matrix A, n steps and an identity matrix I:
exp(A) = I + A + 1/2!*AA + 1/3!*AAA + ... +1/n!*AAA..
The code follows here. The method where I'm having the issue is the method exponential(Matrix A, int nSteps). The methods involved are enclosed, and the Matrix objects take the arguments (int m, int n) to create an array of size double[m][n].
public static Matrix multiply(Matrix m1, Matrix m2){
if(m1.getN()!=m2.getM()) return null;
Matrix res = new Matrix(m1.getM(), m2.getN());
for(int i = 0; i < m1.getM(); i++){
for(int j = 0; j < m2.getN(); j++){
res.getArray()[i][j] = 0;
for(int k = 0; k < m1.getN(); k++){
res.getArray()[i][j] = res.getArray()[i][j] + m1.getArray()[i][k]*m2.getArray()[k][j];
}
}
}
return res;
}
public static Matrix identityMatrix(int M){
Matrix id = new Matrix(M, M);
for(int i = 0; i < id.getM(); i++){
for(int j = 0; j < id.getN(); j++){
if(i==j) id.getArray()[i][j] = 1;
else id.getArray()[i][j] = 0;
}
}
return id;
}
public static Matrix addMatrix(Matrix m1, Matrix m2){
Matrix m3 = new Matrix(m1.getM(), m2.getN());
for(int i = 0; i < m3.getM(); i++){
for(int j = 0; j < m3.getN(); j++){
m3.getArray()[i][j] = m1.getArray()[i][j] + m2.getArray()[i][j];
}
}
return m3;
}
public static Matrix scaleMatrix(Matrix m, double scale){
Matrix res = new Matrix(m.getM(), m.getN());
for(int i = 0; i < res.getM(); i++){
for(int j = 0; j < res.getN(); j++){
res.getArray()[i][j] = m.getArray()[i][j]*scale;
}
}
return res;
}
public static Matrix exponential(Matrix A, int nSteps){
Matrix runtot = identityMatrix(A.getM());
Matrix sum = identityMatrix(A.getM());
double factorial = 1.0;
for(int i = 1; i <= nSteps; i++){
sum = Matrix.multiply(Matrix.scaleMatrix(sum, factorial), A);
runtot = Matrix.addMatrix(runtot, sum);
factorial /= (double)i;
}
return runtot;
}
So my question is, how should I modify my code, so that I can input a matrix and a number of timesteps to calculate the exponential of said matrix after said timesteps?
My way to go would be to keep two accumulators :
the sum, which is your approximation of exp(A)
the nth term of the series M_n, that is A^n/n!
Note that there is a nice recursive relationship with M_n: M_{n+1} = M_n * A / (n+1)
Which yields :
public static Matrix exponential(Matrix A, int nSteps){
Matrix seriesTerm = identityMatrix(A.getM());
Matrix sum = identityMatrix(A.getM());
for(int i = 1; i <= nSteps; i++){
seriesTerm = Matrix.scaleMatrix(Matrix.multiply(seriesTerm,A),1.0/i);
sum = Matrix.addMatrix(seriesTerm, sum);
}
return sum;
}
I totally understand the sort of thrill that implementing such algorithms can give you. But if this is not a hobby project, I concur that you should that you should use a library for this kind of stuff. Making such computations precise and efficient is really not a trivial matter, and a huge wheel to reinvent.
My problem is based on the compound interest formula. A = P(1 + r)^n. I have a number of values for r and n which I must store as an array. I also must output my range of final values A as an array also. I think I have stored r and n correctly as an array. However my problem is with the final values of A and storing each value A. SO far this is what I have written.
import java.util.Scanner;
import javax.swing.*;
public class Prin {
public static void main (String [] args){
System.out.println("Please enter the Principal you wish to invest =>");
Scanner stdio = new Scanner (System.in);
int principal = stdio.nextInt();
stdio.nextLine();
System.out.println("This program will now calculate the final amount A for (years) n = 1,2,3,4 and the rate r = 1%, 1.5%, 2%, 2.5%, 3%");
int yearsarray[] = {1,2,3,4};
double ratearray[] = {0.010, 0.015, 0.020, 0.025, 0.030};
double amountarray[];
amountarray = new double[19];
for(int i=0; i<=3; i++)
{
for(int j=0; j<=5; j++){
amountarray[k] = principal * Math.pow((1 + ratearray[j]), yearsarray[i]);
System.out.println(" answer " + amountarray[k] );
}
}
Do I need another for loop to increase the values of k in amountarray[]?
I would like to have all values of amountarray i.e amountarray[0], amountarray[1], amountarray[2], .......and so on.
Thanks in advance for any help.
amountarray = new double[19];
The code above is false because you need to have 4x5 = 20 double values
This code will always work properly, You should use this and you need to learn write your codes like this:
public class Prin {
public static void main (String [] args){
//...
int[] yearsarray = {1,2,3,4};
double[] ratearray = {0.010, 0.015, 0.020, 0.025, 0.030};
double[] amountarray = new double[yearsarray.length * ratearray.length];
int k = 0;
for(int i=0; i<yearsarray.length; i++){
for(int j=0; j<ratearray.length; j++){
amountarray[k] = principal * Math.pow((1 + ratearray[j]), yearsarray[i]);
System.out.println(" answer " + amountarray[k] );
k++;
}
}
"This program will now calculate the final amount A for (years) n = 1,2,3,4 and the rate r = 1%, 1.5%, 2%, 2.5%, 3%"
... this implies your answer comes in the form of a 2-dimensional matrix.
Hence your amountarray needs to be defined as:
double amountarray[][] = new double[yearsarray.length][ratearray.length];
Then you would calculate:
amountarray[i][j] = principal * Math.pow((1 + ratearray[j]), yearsarray[i]);
No, you don't
int k=0; // initialization
for(int i=0; i<=3; i++)
{
for(int j=0; j<=5; j++){
// use post-increment
amountarray[k] = principal * Math.pow((1 + ratearray[j]), yearsarray[i]);
System.out.println(" answer " + amountarray[k] );
// now we can increment k
k = k+1;
}
Also this: as you seem to be using yearsarray just to get a value that's i+1, why just not do
amountarray[k] = principal * Math.pow((1 + ratearray[j]), i+1);
That way you can get rid of yearsarray, at least in this case
EDIT: a reworked version that also handles a couple of other minor issues and reduced usage of "magic numbers"
public class Prin {
public static void main(String[] args) {
System.out.println("Please enter the Principal you wish to invest =>");
Scanner stdio = new Scanner(System.in);
int principal = stdio.nextInt();
stdio.nextLine();
System.out.println("This program will now calculate the final amount A for (years) n = 1,2,3,4 and the rate r = 1%, 1.5%, 2%, 2.5%, 3%");
int yearsarray[] = {1, 2, 3, 4};
double ratearray[] = {0.010, 0.015, 0.020, 0.025, 0.030};
double amountarray[];
// this way the array will follow the size of yearsarray and ratearray
amountarray = new double[yearsarray.length * ratearray.length];
int k = 0; // initialization
for (int i = 0; i <= yearsarray.length; i++) {
System.out.println("years=" + yearsarray[i]);
for (int j = 0; j < ratearray.length; j++) {
// use post-increment
amountarray[k] = principal * Math.pow((1 + ratearray[j]), yearsarray[i]);
System.out.println(" " + ratearray[j] + " answer " + amountarray[k]);
k+=1;
}
}
}
}
Try to store your data in a Map, this is an example of your loop
for(int i=0; i<=yearsarray.length; i++) {
for(int j=0; j<=ratearray.length; j++) {
double answer = (yearsarray, principal * Math.pow((1 + ratearray[j]), yearsarray[i]));
Collection<Double> aux;
if (!answers.containsKey(yearsarray[i])){
aux = new ArrayList<Double>();
aux.add(answer);
} else {
aux = answers.get(yearsarray[i]);
aux.add(answer);
}
answers.put(yearsarray[i], aux);
// include the answers in a Map
}
}
Thanks
I am trying to write a program that will, when executed, will go through an array and remove all instances of 0.0 and change the size of the array equal to the number of non zero elements and put those elements in their previous order. That is, if n=10 and the contents of a[j], j = 0 to n - 1 are initially
0.0, 1.2, 0.0, 0.0, 0.0, 2.3, 0.0, 9.7, 5.6, 0.0
then after execution of the code the contents should be
n=4, a[0]=1.2, a[1]=2.3, a[2]=9.7, and a[3]=5.6.
This is what I have so far:
import java.util.Scanner;
public class hw2
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
final double KEY = 0.0;
int n = scan.nextInt();
double[] a = new double[n];
for(int i=0; i<n; i++)
{
a[i] = scan.nextDouble();
}
for(int k = 0; k<n; k++)
{
if(a[k] == KEY)
{
a[k] = a[k+1];
n--;
}
System.out.println(a[k]);
}
}
}
Just a little nudge in the right direction would be appreciated.
Consider using an ArrayList, which will allow you to add items when you want, grow as needed, and maintain an accurate count.
Although in this case, if you wanted/needed to use an array, you could simply not save the value if it's "0", perhaps. (Also don't increment the "used array variable", except when you add, so you know how much contains "non 0" data or treat the first "0" encountered during iteration as "end of useful data" -- arrays are initialized with the default value of the type.)
If you want to go from an array with zeros to an array with no zeros at all, you must use two passes -- one to count the non-zeros, to construct a new array of the appropriate size, and then copy the non-zero values over. This could be done in reverse as well (compact the initial array, and then copy the "filled" portion of it over), but it's slightly more complicated.
If you do continue with your current approach (which the result array will have zeros, but at the end), you need to maintain two index pointers -- one is the primary loop iterator, the second is the next place to put the non-zero value, which is incremented only when a value is copied (or not moved, as when both indexes are the same, which will be the case until the first 0 is encountered). Make sure to "zero" the place you move the non-zero from. The number of moves can be reduced if order does not need to be preserved.
Your implementation (2nd for loop) is not right, it will fail to simple test case:
Input > 5 2.0 2 0.0 3 0.0
Your program will have wrong output:
2.0
2.0
3.0
3.0
but it should be 2.0 2.0 3
Also, you can't use == to compare two double.
The following code is my solution basing on your current code:
public class hw21 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
final double KEY = 0.0;
final Double ACCEPTABLE_TOLERANCE = 0.000000000001d;
int n = scan.nextInt();
double[] a = new double[n];
for (int i = 0; i < n; i++) {
a[i] = scan.nextDouble();
}
for (int k = 0, j = 0; k < n; k++) {
if (Math.abs(a[k] - KEY) < ACCEPTABLE_TOLERANCE) {
continue;
}
a[j] = a[k];
System.out.println(a[j]);
j++;
}
}
}
Also I prefer to use an ArrayList like below:
public class hw2 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
final double KEY = 0.0;
final Double ACCEPTABLE_TOLERANCE = 0.000000000001d;
int n = scan.nextInt();
double[] a = new double[n];
for (int i = 0; i < n; i++) {
a[i] = scan.nextDouble();
}
List<Double> newList = new ArrayList<Double>();
for (int k = 0; k < n; k++) {
if (Math.abs(a[k] - KEY) < ACCEPTABLE_TOLERANCE) {
continue;
}
newList.add(a[k]);
}
System.out.println("There are " + newList.size() + " no-zero double:");
System.out.println(newList);
}
}
import java.util.Arrays;
import java.util.Scanner;
public class StackOverflow1
{
public static final double KEY = 0.0;
private static final Scanner INPUT = new Scanner(System.in);
public static void main(String[] args) {
int length = INPUT.nextInt();
double[] array = new double[length];
for(int i=0; i<length; i++) {
array[i] = INPUT.nextDouble();
}
int index = 0;
for(int k = 0; k < length ; k++) {
if(array[k] == KEY) {
continue;
}
array[index] = array[k]; // bring the non-zeroth element forward
if (index != k) array[k] = 0; //make the non-zeroth element zero in the actual location
index++;
}
System.out.println("n = " + index + " array = " + Arrays.toString(array));
}
}
you can remove those unwanted zeros as follows but in this case it get sorted.
#org.junit.Test
public void test15() throws Exception {
double[] arr = new double[]{0.0,1.1,0.1,0.0,2.1};
double[] nonZeroArr = arr;
Arrays.sort(nonZeroArr);
int index = -1;
while((index = Arrays.binarySearch(nonZeroArr, 0.0)) > -1){
double[] newArr = new double[nonZeroArr.length-index-1];
System.arraycopy(nonZeroArr, index+1, newArr, 0, newArr.length);
nonZeroArr = newArr;
}
for (double d : arr) {
System.out.print(d +",");
}
System.out.println();
for (double d : nonZeroArr) {
System.out.print(d + ",");
}
}
IF you want to sound really smart in class point out that this is a one liner in a lot of languages that are more productive than Java :)