Java loop required - java

I'm quite new to coding, as you all can see from the clumsy code below. However, looking at this code you can see what I'm getting at. The code basically does what its supposed to, but I would like to write it as a loop to make it more efficient. Could someone maybe point me in the right direction? I have done some digging and thought about recursion, but I haven't been able to figure out how to apply it here.
public static void main(String[] args) {
double a = 10;
double b = 2;
double c = 3;
double avg = (a + b + c)/3;
double avg1 = (avg + b + c)/3;
double avg2 = (avg1 + b + c)/3;
double avg3 = (avg2 + b + c)/3;
System.out.println(avg+ "\n" + avg1+ "\n"+ avg2 + "\n"+ avg3);
}

Functionally, this would be equivalent to what you have done:
public static void main(String[] args) {
double a = 10;
double b = 2;
double c = 3;
double avg = (a + b + c)/3;
System.out.println(avg);
for (int i=0; i<3; i++) {
avg = (avg + b + c)/3;
System.out.println(avg);
}
}
But also you should know that shorter code does not always mean efficient code. The solution may be more concise, but I doubt there will be any change in performance.

If you mean shorter code with efficieny you can do it like this.
public static void main(String[] args) {
double a = 10;
double b = 2;
double c = 3;
for (int i = 0; i < 4; i++) {
a = (a + b + c) / 3;
System.out.println(a);
}
}

I have no idea what this calculation represents (some sort of specialised weighted average?) but rather than use repetition and loops, you can reach the exact same calculation by using a bit of algebra and refactoring the terms:
public static double directlyCalculateWeightedAverage(double a, double b,
double c) {
return a / 81 + 40 * b / 81 + 40 * c / 81;
}
This reformulation is reached because the factor a appears just once in the mix and is then divided by 34 which is 81. Then each of b and c appear at various levels of division, so that b sums to this:
b/81 + b/27 + b/9 + b/3
== b/81 + 3b/81 + 9b/81 + 27b/81
== 40b/81
and c is treated exactly the same.
Which gives the direct calculation
a/81 + 40b/81 + 40c/81
Assuming your formula does not change, I'd recommend using this direct approach rather than resorting to repeated calculations and loops.

Your problem can be solved by 2 approaches: iterative (with a loop) or recursive (with a recursive function).
Iterative approach : for loop
The for loop allow you to repeat a group of instructions au given number of times.
In your case, you could write the following :
double a = 10, b = 2, c = 3;
double avg = a;
for (int i = 0; i < 4; i++) {
avg = (avg + b + c) / 3;
System.out.println(avg);
}
This will print the 4 first results of your calculation.
In my example, I overwrite the variable avg to only keep the last result, which might not be what you want. To keep the result of each loop iteration, you may store the result in an array.
Recursive approach
In Java, there is no such thing as a standalone function. In order to use recursion, you have to use static methods :
private static double recursiveAvg(double avg, int count) {
// Always check that the condition for your recursion is valid !
if (count == 0) {
return avg;
}
// Apply your formula
avg = (avg + 2 + 3) / 3;
// Call the same function with the new avg value, and decrease the iteration count.
return recursiveAvg(avg, count - 1);
}
public static void main(String[] args) {
// Start from a = 10, and repeat the operation 4 times.
double avg = recursiveAvg(10, 4);
System.out.println(avg);
}
Always check for a condition that will end the recursion. In our example, it's the number of times the operation should be performed.
Note that most programmers prefer the iterative approach : easier to write and read, and less error prone.

Related

How to add multiple numbers using nested loops?

I am doing an assignment where I must use nested loops in order to add up the squares and cubes of integers from 1 to N (N being whatever the user inputs). For example, if the user input the number 5, the program is supposed to do "1²+2²+3²+4²+5²" and output the sum of those numbers, as well "1³+2³+3³+4³+5³" and output the sum of those numbers.
However, I am having trouble figuring out how to code it in a way that I receive the proper output? This is what I wrote. Scanners were already added.
int limitNum = input.nextInt();
double squareNums:
double sumofSq = 0;
double cubedNums;
double sumofCubes = 0;
for(int s = 1; s <= limitNum; s++)
{
for(int c = 1; c <= limitNum; c++)
{
cubedNums = Math.pow(c, 3);
sumofCubes = sumofCubes + cubedNums;
}
squareNums= Math.pow(s, 2);
sumofSq = sumofSq + squareNums;
}
But currently, when I run this program, the sum of the squares output correctly, but the sum of the cubes is always some big number. For example if 5 is used, sumofSq would output 55.0, but sumofCubes would output 1125.0.
There is no point using a nested loop as this would result in complexity of O(n²). A single loop would be sufficient and be in complexity class O(n).
public class Application {
public static void main(String[] args) {
var squareSum = 0d;
var cubeSum = 0d;
var upperBound = 5;
for(var i = 1; i <= upperBound; i++){
squareSum += Math.pow(i, 2);
cubeSum += Math.pow(i, 3);
}
System.out.printf("""
Sum of first n squares: %s
Sum of first n cubes: %s
""", (int)squareSum, (int)cubeSum);
}
}
In fact there is no need to loop at all => constant computation time no matter the size of the input O(1). There is a well known formula which tells you the sum of the first n squares.
n(n+1)(2n+1)
------------
6
Please see this for a proof.
The same holds true for the first n cubes.
n²(n+1)²
--------
4
Please see this for a proof.
The following program will therefore return the same result.
public class Application {
public static void main(String[] args) {
var upperBound = 5;
System.out.printf("""
Sum of first n squares: %s
Sum of first n cubes: %s
""", sumOfFirstNSquares(upperBound), sumOfFirstNCubes(upperBound));
}
public static int sumOfFirstNSquares(int n){
return (n * (n+1) * (2 * n + 1)) / 6;
}
public static int sumOfFirstNCubes(int n){
return ((n * n) * (n+1) * (n+1)) / 4;
}
}
In fact there is no need to loop at all => constant computation time no matter the size of the input O(1). There is a well known formula which tells you the sum of the first n squares.
java

Does the JIT Optimizer Optimize Multiplication?

In my computer architecture class I just learned that running an algebraic expression involving multiplication through a multiplication circuit can be more costly than running it though an addition circuit, if the number of required multiplications are less than 3. Ex: 3x. If I'm doing this type of computation a few billion times, does it pay off to write it as: x + x + x or does the JIT optimizer optimize for this?
I wouldn't expect to be a huge difference on writing it one way or the other.
The compiler will probably take care of making all of those equivalent.
You can try each method and measure how long it takes, that could give you a good hint to answer your own question.
Here's some code that does the same calculations 10 million times using different approaches (x + x + x, 3*x, and a bit shift followed by a subtraction).
They seem to all take approx the same amount of time as measured by System.nanoTime.
Sample output for one run:
sum : 594599531
mult : 568783654
shift : 564081012
You can also take a look at this question that talks about how compiler's optimization can probably handle those and more complex cases: Is shifting bits faster than multiplying and dividing in Java? .NET?
Code:
import java.util.Random;
public class TestOptimization {
public static void main(String args[]) {
Random rn = new Random();
long l1 = 0, l2 = 0, l3 = 0;
long nano1 = System.nanoTime();
for (int i = 1; i < 10000000; i++) {
int num = rn.nextInt(100);
l1 += sum(num);
}
long nano2 = System.nanoTime();
for (int i = 1; i < 10000000; i++) {
int num = rn.nextInt(100);
l2 += mult(num);
}
long nano3 = System.nanoTime();
for (int i = 1; i < 10000000; i++) {
int num = rn.nextInt(100);
l3 += shift(num);
}
long nano4 = System.nanoTime();
System.out.println(l1);
System.out.println(l2);
System.out.println(l3);
System.out.println("sum : " + (nano2 - nano1));
System.out.println("mult : " + (nano3 - nano2));
System.out.println("shift : " + (nano4 - nano3));
}
private static long sum(long x) {
return x + x + x;
}
private static long mult(long x) {
return 3 * x;
}
private static long shift(long x) {
return (x << 2) - x;
}
}

Finding a "correct" value that is unknown prior to a calculation

The problem is as follows i have a large or small number (can be either one) and i need to tweak this number and put it through a caluclation. Given the result of the calulation it has to mach a certain value on the 5th decimal at least.
So i need to make a method that takes this starting value, tries to increase or decrease it given what the current result is until i get the correct result. I have made some atempts with no success.
Here is an example that won't woork at all but it hints towards what i mean... (this is just a small scale test case)
public class Test {
public static void main(String[]args)
{
double ran = 100 + (int)(Math.random() * 100000.999999999);
int count = 0;
double tmpPay = 3666.545;
double top = tmpPay;
double low = 0;
while ( tmpPay != ran )
{
if ( tmpPay > ran)
{
if( low == 0)
{
tmpPay = top / 2;
top = tmpPay;
}
else
{
tmpPay = tmpPay + ((top - low) / 2);
top = tmpPay;
}
}
if (tmpPay < ran)
{
tmpPay = top * 1.5;
low = top;
top = tmpPay;
}
}
System.out.println(" VAlue of RAN: " +ran + "----VALUE OF tmpPay: " + tmpPay + "---------- COUNTER: " + count);
}
Example 2 mabey a more clear description. This is my solution now..
guessingValue = firstImput;
while (amortization > tmpPV)
{
guessingValue -= (decimal)1;
//guessingVlue -- > blackbox
amortization = blackboxResults;
}
while (amortization < tmpPV)
{
guessingValue += (decimal)0.00001;
//guessingVlue -- > blackbox
amortization = blackboxResults;
}
}
As I already mentioned in the comment above you should not compare doubles using build-in operators. This is the main reason why your code is not working. The second one is that in else clause tmpPay = tmpPay + ((top-low) /2); instead of tmpPay = tmpPay - ((top-low) /2 );
Complete fixed code is below :
public class Test {
private static final double EPSILON = 0.00001;
public static boolean isEqual( double a, double b){
return (Math.abs(a - b) < EPSILON);
}
public static void main(String[]args)
{
double ran = 100 + (int)(Math.random() * 100000.999999999);
int count = 0;
double tmpPay = 3666.545;
double top = tmpPay;
double low = 0;
while ( !isEqual(tmpPay, ran))
{
if ( tmpPay > ran)
{
if( isEqual(low, 0.0))
{
tmpPay = top / 2;
top = tmpPay;
}
else
{
tmpPay = tmpPay - ((top - low) / 2);
top = tmpPay;
}
}
if (tmpPay < ran)
{
tmpPay = top * 1.5;
low = top;
top = tmpPay;
}
System.out.println("RAN:"+ran+" tmpPay:"+tmpPay+" top:"+top+" low:"+low+" counter:"+count);
count++;
}
System.out.println(" VAlue of RAN: " +ran + "----VALUE OF tmpPay: " + tmpPay + "---------- COUNTER: " + count);
}
}
One way would be to define your problem as a local optimization task and use an local optimizer (for example Brent's method or Nelder Mead Simplex from Apache commons).
Your goal function here would be the distance between the desired value and what you get from your black box.
If I understand correctly, you have a function g(x) and a value K, you want to find x0 such that g(x0) = K.
This is equivalent to find the roots of the function f(x) = g(x) - K, because f(x0) == f(x0) - K == K - K == 0.
A simple algorithm would be Newton's method.
If trying to run the program, it will easily be in infinite loop, since the while condition (for double values comparison) could hardly equal.
e.g.
There are 2 values as follows:
double value1 = 3666.545;
double value2 = 3666.54500001;
value1 == value2 is false.
Even this kind of values are not equal.
You'd better define a range for deviation.
e.g, if |value1 - value2| < 0.005, then break the while condition and print the random num information.

Algorithm to find all possible values of A^5 + B^5 + C^5?

im trying to write an algorithm that will find all the possible values of A^5 + B^5 + C^5 when the user inputs a number 'N'.
For example if N=100 I want to make an array that contains all the possible values where each slot in the array contains a number that was found by plugging in numbers between 1-100 for A^5 + B^5 + C^5. So one of the positions in the array contains 1 from (1^5 + 1^5 + 1^5). Another position in the array contains
the number 355447518 (from 19^5 + 43^5 + 46^5). So there will be 100^3 elements in my array.
public long[] possibleValues(int n)
{
long[] solutionSet = new long[(int) Math.pow(n, 3)];
for(int i=1;i<=n;i++)
{
solutionSet[i] = ((long) Math.pow(i, 5) + (long) Math.pow(i, 5) + (long) Math.pow(i, 5));
//testing purposes
System.out.println(i +"^5 " + "+" + i+"^5 " + "+" + i+"^5" + "=" + solutionSet[i]);
}
return solutionSet;
}
thats what I have so far, but my problem is that it doesn't do all the permutations of N. What is the best way to get all possible permutations of N? Am i making this more complicated than necessary? How would I arrange all possible (A, B, C)'s ?
Use nested forloops:
index=0;
for (int i=1;i<=n;i++){
for (int j=1;i<=n;j++){
for (int k=1;i<=n;k++){
solutionSet[index++] = ((long) Math.pow(i, 5) + (long) Math.pow(j, 5) + (long) Math.pow(k, 5));
}
}
}
You can calculate all powers quicker by using an array containing all fifth powers up to N.
You're using i for all 3 terms, thus you're essentially calculating permutations of
A^5 + A^5 + A^5 = 3A^5.
You need a 3-dimensional array and 3 for loops.
public long[][][] possibleValues(int n)
{
long[][][] solutionSet = new long[n+1][n+1][n+1];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
{
solutionSet[i][j][k] = ((long) Math.pow(i, 5) + (long) Math.pow(j, 5) + (long) Math.pow(k, 5));
//testing purposes
System.out.println(i +"^5 " + "+" + j+"^5 " + "+" + k+"^5" + "=" + solutionSet[i][j][k]);
}
return solutionSet;
}
If you indeed only want a 1-dimensional array, you'll do something similar to the above, just have a separate variable for the index:
Since you probably don't want excessive repetition of values, you can probably start j from i and k from j.
public long[] possibleValues(int n)
{
long[] solutionSet = new long[n*n*n];
int c = 0;
for(int i = 1; i <= n; i++)
for(int j = i; j <= n; j++)
for(int k = j; k <= n; k++)
{
solutionSet[c] = ((long) Math.pow(i, 5) + (long) Math.pow(j, 5) + (long) Math.pow(k, 5));
//testing purposes
System.out.println(i +"^5 " + "+" + j+"^5 " + "+" + k+"^5" + "=" + solutionSet[c]);
c++;
}
return solutionSet;
}
Some significant optimizations can still be done:
Math.pow isn't particularly efficient, as Peter mentioned.
For the first version, you can derive values from previous values in certain circumstances.
The really brute-force way to do it would require three nested loops:
for(int a = 1; a <= n; ++a)
{
for(int b = 1; b <= n; ++b)
{
for(int c = 1; c <= n; ++c)
{
// Add this combination to your array, and print it out.
// It may be more convenient to use ArrayList instead of long[].
}
}
}
Note that for this takes O(n^3) time, so n doesn't have to be very large before it will take forever to compute (and also use up all of your memory).
Use three loops. One each for A, B, C. This is a pseudo code and does not adhere to java syntax
for(int A:100){
for(int B:100){
for(int C:100) {
calculate A^5 * B^5 * C^5
}
}
}
I agree with the other answers about nested forloops. For better performance it may be profitable to store the answers in a hash table so that you don't recalculate the same value. For instance, you calculate 15^5 then you store that answer in an array like ans['155'] = 759375. So when you go to calculate 15^5 again you can do an if statement if(ans[num.tostring+'5']) then use that value instead of calculating 15^5 again.
Starting from #Dukeling previous answer:
I use a powers array to compute the powers just n times (not n*n*n)
public static void test(int n){
long[] powers = new long[n+1];
for (int i=0; i<powers.length; i++)
powers[i] = (long) Math.pow(i, 5);
long[][][] solutionSet = new long[n+1][n+1][n+1];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
{
solutionSet[i][j][k] = ((long) powers[i] + (long) powers[i] + (long) powers[i]);
//testing purposes
System.out.println(i +"^5 " + "+" + j+"^5 " + "+" + k+"^5" + "=" + solutionSet[i][j][k]);
}
}
I believe you are looking for a combination and not a permutation. It also seems that you want A, B, and C to be all possible values from 1 to N. In that case, you'll want to make your nested for loop as such to only calculate the combinations:
for (int a = 0; a < n; a++) {
for (int b = 0; b <= a; b++) {
for (int c = 0; c <= b; c++) {
pow5(a) + pow5(b) + pow5(c);
}
}
}
You'll also want to use a lookup table which could be loaded from a file. The more values in your lookup table, the faster your algorithm will perform. In my opinion, the best method will reduce the number of operations required. That means not calculating every value at runtime. Alternatively, you could also optimize for memory usage and just use a simple algorithm. Additionally, you'll want to measure the performance of the algorithm. Here is an example.
// for all number > 0 and <= 25
public static final double[] powersOf5 = {1.0, 32.0, 243.0, 1024.0, 3125.0,
7776.0, 16807.0, 32768.0, 59049.0, 100000.0, 161051.0, 248832.0, 371293.0,
537824.0, 759375.0, 1048576.0, 1419857.0, 1889568.0, 2476099.0, 3200000.0,
4084101.0, 5153632.0, 6436343.0, 7962624.0, 9765625.0};
// calc pow(i, 5) and use a lookup table for small values i
public static double pow5(int i) {
if (i > 0 && i <= 25) {
return powersOf5[i-1];
} else {
return Math.pow(i, 5);
}
}
public static void main(String[] args) {
long start = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
System.out.println(pow5(i));
}
long end = System.currentTimeMillis();
System.out.println("Execution time: " + (end - start) + " ms");
}
have a think at first
1. 1^5 + 2^5 + 3^5 = 3^5 + 2^5 +1^5 , So i<j<k
for(i=0;i<N;i++)
for(j=i;j<N;j++)
for(k=j;k<N;k++)
2. A^5+B^5+C^5=D^5+E^5+F^5
If we use array , there may be lots of same value in it.
we can use Set to save memory, if time is not the most important.
3. A^5 cannot be saved by Long type, when A is too big.
So, do we make sure N is little? otherwise, there may be a bug.
4. Multiplication cost lots of time.
Give a example, if N=100, to get all result, how many times does it spend
calc 5^5.
5^5+1^5+1^5
5^5+1^5+2^5
5^5+1^5+3^5
...
How about if there is an array save the answer
define array[i] = i^5
Then it save our time;
Just think more, Algorithm is something that like this
Now let's talk more about Math.pow();
Yes it's a good method that help you, but this is an algorithm which is impl, we just want to know A^5, not A^N, the second parameter is static;
Why not impl a method by yourself.
First, we try to impl a method like this
public Long powOf5(Long A){
return A*A*A*A*A;
}
Then, we find we can optimize it.
public Long powOf5(Long A){
Long A2 = A*A;
return A2*A2*A;
}
This multiply 3 times, that multiply 4 times;
I am sure this method is faster than Math.pow()

Java JScience: How to print the whole Real number?

I wrote some testing code which calculated Pi to whatever thing I wanted it to calculate to. It looks something like this:
public static void piCalculatorMethod1() {
int iteration = 1000000;
Real pi = Real.valueOf(0);
for (int i = 1; i < iteration + 1; i++) {
Real current = pi;
Real addendum = Real.valueOf((1/Math.pow(i, 2)));
pi = current.plus(addendum);
}
pi = pi.times(6);
pi = pi.sqrt();
System.out.println(pi.toString());
}
Quite unfortunately, the output decides it would look like this:
3.14159169866
I'm quite sure the end value is much more accurate than that, because I've seen what values they are actually adding, and that's much more accurate than that.
How do I get System.out.println to show me the whole Real instead of just the first few digits?
You may need to question your assumption about the convergence of the series. This approximation of π relies on Euler's solution to the Basel problem. Empirically, the example below finds the deviation from π2/6 for a number of iteration counts. As you can see, each order of magnitude in the iteration count adds no more than one decimal digit of accuracy.
Code:
Real PI_SQUARED_OVER_6 = Real.valueOf(Math.pow(Math.PI, 2) / 6);
for (int p = 0; p < 7; p++) {
int iterations = (int) Math.pow(10, p);
Real pi = Real.valueOf(0);
for (int i = 1; i < iterations + 1; i++) {
pi = pi.plus(Real.valueOf(1 / Math.pow(i, 2)));
}
System.out.println("10^" + p + ": " + PI_SQUARED_OVER_6.minus(pi));
}
Console:
10^0: 6.44934066848226E-1
10^1: 9.5166335681686E-2
10^2: 9.950166663334E-3
10^3: 9.99500166667E-4
10^4: 9.9995000167E-5
10^5: 9.999950000E-6
10^6: 9.99999500E-7

Categories

Resources