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
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;
}
}
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.
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()
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