I'm sure I'm making a rookie mistake with java(this is actually my first program). I am trying to port some working python code I made into java(as a learning/testing exercise to learn a bit of the differences) but I'm getting different results between the two.
My program takes a list of data and generates another list based on it(basically sees if a value can be broken down by a sum). Python correctly gives 2,578 results while Java only gives 12. I tried to find the same commands in java and thought I did but can't seem to figure out why the results differ(the difference between the two I have experienced problems with multi threading and syncing of variables, wasn't sure if Java was doing anything behind the scenes so I had a while loop to keep running until the results stabilize, but it didn't help). Any suggestions would be helpful.
Here's the offending code(java at the top, python and pseudo code commented out in the bottom as reference):
for (int c = 0; c <= max_value; c++){
String temp_result = (s - c * data.get(i) + "," + i);
if( results.contains( temp_result ) ){
String result_to_add = (s + "," + i+1);
if( results.contains( result_to_add ) ){
System.out.println("contains result already");
} else {
results.add(result_to_add);
} print len(T)
#Here's the basic pseudo code(I added a few control variables but here's a high level view):
for i = 1 to k
for z = 0 to sum:
for c = 1 to z / x_i:
if T[z - c * x_i][i - 1] is true:
set T[z][i] to true
*/
In java s + "," + i+1 is a String concatenation : "10" + "," + 4 + 1 will return 10,41.
Use String result_to_add = s + "," + (i+1); instead.
I see you've solved it just now, but since I've written it already, here's my version:
This uses the trick of using a Point as a substitute for a 2-element Python list/tuple of int, which (coincidentally) bypasses your String concatenation issue.
public class Sums
{
public static void main(String[] args)
{
List T = new ArrayList();
T.add(new Point(0, 0));
int target_sum = 100;
int[] data = new int[] { 10, -2, 5, 50, 20, 25, 40 };
float max_percent = 1;
int R = (int) (target_sum * max_percent * data.length);
for (int i = 0; i < data.length; i++)
{
for (int s = -R; s < R + 1; s++)
{
int max_value = (int) Math.abs((target_sum * max_percent)
/ data[i]);
for (int c = 0; c < max_value + 1; c++)
{
if (T.contains(new Point(s - c * data[i], i)))
{
Point p = new Point(s, i + 1);
if (!T.contains(p))
{
T.add(p);
}
}
}
}
}
System.out.println(T.size());
}
}
Related
I'm trying to figure out a way to make my simple map generation better. So the question to be specific is, how do I make my random 2-D array platform generator, less random so it looks more like a platformer game level as well as adding a bit more variables to it for adding variation to each Map Generated. Explanation below.
Currently, I have this:
void GenerateMap() {
int x = width/30;
int y = height/28;
int[][] map = new int[x][y];
//println(map.length);
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[i].length; j++) {
float val = random(0, 100);
float nv = noise(val);
println(nv);
if (j <= (int) (.5 * map.length)) {
map[i][j] = nv < .3 ? 0 : 1;
} else if (j >= (int) (.7 * map.length)) {
map[i][j] = nv < .6 ? 1 : 0;
} else {
map[i][j] = nv <= .3 ? 0 : 1;
}
println(i +"-" + j + " - rowcol: " + map[i][j]);
}
}
levelMap = map;
JSONArray saveArr = arrayToJson(levelMap);
saveJSONArray(saveArr, dataPath("./maps/Generation_" + mapGenerations + ".json"), "compact");
}
It builds a 2d array with 1s and 0s, I tried to make it less random so it looks like a playable terrain. the top-most section will be 0's (air), the bottom-most will be 1's (platform). Then the middle will have a mix to make floating platforms and such. So far I've got nothing.
The next Idea that popped up was to have the number go from 0-N. This works by:
0 will always be air,
1 will always be a platform,
2 can be a platform of a different image, let's say a diagonal platform to form a slope off the edge
3 can be a collectible or anything
...etc
My issue is I can't figure out how to generate the numbers in a way that will make the map not look like a mess. I came up with a setup for my variables:
public int[] toplayer = null, // [0,0,0,0,...,0]
bottomlayer = null, // [1,1,1,1,...,1]
variation = {0,1,2}, // the 0-N
variationRatios = {60, 30, 10}; // this would specify the frequency/probability of each variation show up, respectively, in a random() function
After all, that's done, then I run a function to replace all values with their respective "Sprite" and then display them on the screen.
void drawPlatform(int amt, PVector pos, PVector size) {
for (int i = 0; i < amt; i++) {
//new Platform(new PVector(abs(width-((pos.x+(size.x/2)) + (i * size.x))), pos.y+(size.y/2)), size);
Platform p = new Platform(new PVector(abs(((pos.x+(size.x/2)) + (i * size.x))), pos.y+(size.y/2)), size);
if (platforms.indexOf(p) % 5 == 0 && !p.bouncy) {
p.bouncy = true;
}
}
}
JSONArray arrayToJson(int[][] arr) {
JSONArray ja = new JSONArray();
for (int[] ar : arr) {
JSONArray j = new JSONArray();
ja.append(j);
for (int a : ar) {
j.append(a);
}
}
return ja;
}
void LoadMap(int[][] map) {
drawPlatform(width/30, new PVector(0, 0), new PVector(30, 30)); // top
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[i].length; j++) {
if (map[i][j] == 0) {
new Platform(new PVector((i*30)+15, (j*30)+45), new PVector(30, 30));
//drawPlatform(1, new PVector(i+j*30, (i+j)*30), new PVector(30, 30));
}
}
}
drawPlatform(width/30, new PVector(0, height-30), new PVector(30, 30)); // bottom
println(gameObjects.size() + " GameObjects loaded");
println(platforms.size() + " Platforms loaded");
}
Overall, this is how it's used:
GenerateMap();
LoadMap(levelMap);
mapGenerations++;
This is how it would end up looking (obviously different each generation):
But right now, I have something like this:
I've looked everywhere for a couple of days now, for a solution and can't find anything as specific as my request. If you have any ideas, please let me know.
Quick Note: Of course, we could have the user write the array by hand but that's not time-effective enough. I could also have a visual map builder but that's a lot more code and more time than I have available. I am not opposed to this idea, however.
I have this project that I have been working on, but I'm a bit rusty so I could use some help to figure out this part.
The main jizt of my project, is that I want to be able to fire a gun at a target and have the target analyze my data.
Before I even start on this, I did some research to find out if anyone else had done this before, and turns out a company in USA have done it, but in a different way than what I imagined..
This is not meant as a business idea, just a fun project for my self :)
Now here is my issue, I ofcourse made a "prototype" without the gun, and without the targets.
All text in Java to see if I could make this work.
I researched a bit since I was rusty (and still am), and figured out most of the problems I faced.
The part that has me stuck is at the very end of it, I have an array for all the shots but I want to divide this array into multiple arrays with the size of the magazine capacity.
How would I accomplish this?
Unfortunately I don't save my code, if I chose to delete it, so my scraps are long gone, but I have tried a few things that came to mind and for several days I havn't been able to figure this one out..
I tried with nested for loops, then I tried again but with nested for loops in a while loop, and I probably tried a few different things aswell.
if (hasrun == true) {
//OUTPUT
ms(2);
System.out.print("You shot the following:");
nl(1);
int counter = 0;
int i = 0;
while (sf > magcap) {
sf-=magcap;
mnm++;
}
while (counter <= mnm) {
System.out.print("Mag " + mn + ": ");
for (i+=0; i < magcap; i++) {
System.out.print(shots[i] + " ");
}
counter++;
mn++;
nl(1);
}
Just to clarify some things in my code here, I know this isn't the cleanest code, I'm not going for clean, and I know I don't need half of my functions (methods), but I did them to practice so they're there. Any help would be greatly appreciated with solving my problem tho! :)
If you want to have a look at all of my code for this project, head over to pastebin
You can use Guava to do it easily,
int[] x = {1,2,3,4,5,6};
int splitSize = 3;
List<Integer> list = IntStream.of(x).boxed().collect(Collectors.toList());
//partition
List<List<Integer>> partitioned = Lists.partition(list, splitSize);
//result: [[1,2,3], [4,5,6]]
Using System.arraycopy:
import java.util.Arrays;
public class Testing {
// static int[] input = {1,2,3,4,5,6}; // testdata
static int[] input = {1,2,3,4,5,6,7}; // testdata
// static int[] input = {1,2,3,4,5,6,7,8}; // testdata
static int magSize = 3; // testdata
// static int magSize = 5; // testdata
public static void main(String[] args) {
// int resultSize = (int) Math.ceil((double) input.length / magSize);
int resultSize = input.length % magSize == 0 ?
input.length/magSize :
input.length/magSize + 1;
int[][] result = new int[resultSize][magSize];
for (int i = 0; i < resultSize; i++) {
System.arraycopy(input, // src
i*magSize, // srcPos
result[i], // dest
0, // destPos
(i + 1) * magSize < input.length ?
magSize :
input.length - i*magSize); // length
}
System.out.println("Original : " + Arrays.toString(input));
System.out.println("Result : " + Arrays.deepToString(result));
/*
prints:
Original : [1, 2, 3, 4, 5, 6, 7]
Result : [[1, 2, 3], [4, 5, 6], [7, 0, 0]]
*/
}
}
I figured it somewhat out, here is what I did. Not quite implemented yet, but this worked with an array.
// OUTPUT
while (sf >= magcap) {
sf -= magcap;
mn++;
}
ms(2);
System.out.println(mn + " mags and " + sf + " shots fired");
nl(2);
for (int i = 0; i < mn; i++) {
from = magcap * magcounter - magcap;
to = magcap * magcounter;
System.out.print("Mag " + magcounter + ": ");
for (int j = from; j < to - 1; j++) {
System.out.print(shots[j] + ", ");
}
System.out.print(shots[to - 1] + ".");
magcounter++;
nl(1);
}
// PRINT THE REST
if (sf >= 1) {
from = magcap * magcounter - magcap;
to = magcap * magcounter;
if (sf == 1) {
System.out.print("Mag " + magcounter + ": ");
System.out.print(shots[from] + ".");
} else {
System.out.print("Mag " + magcounter + ": ");
for (int i = 0; i < sf - 1; i++) {
System.out.print(shots[from + i] + ", ");
}
from += sf -1;
System.out.print(shots[from] + ".");
}
}
The output is
1 2 3 4 5 6 7 8 9 10
3 mags fired and 1 shots fired
Mag 1: 1 2 3
Mag 2: 4 5 6
Mag 3: 7 8 9
Mag 4: 10
I'm not very experienced with Rust and I'm trying to diagnose a performance problem. Below there is a pretty fast Java code (runs in 7 seconds) and what I think should the the equivalent Rust code. However, the Rust code runs very slowly (yes, I compiled it with --release as well), and it also appears to overflow. Changing i32 to i64 just pushes the overflow later, but it still happens. I suspect there is some bug in what I wrote, but after staring at the problem for a long time, I decided to ask for help.
public class Blah {
static final int N = 100;
static final int K = 50;
public static void main(String[] args) {
//initialize S
int[] S = new int[N];
for (int n = 1; n <= N; n++) S[n-1] = n*n;
// compute maxsum and minsum
int maxsum = 0;
int minsum = 0;
for (int n = 0; n < K; n++) {
minsum += S[n];
maxsum += S[N-n-1];
}
// initialize x and y
int[][] x = new int[K+1][maxsum+1];
int[][] y = new int[K+1][maxsum+1];
y[0][0] = 1;
// bottom-up DP over n
for (int n = 1; n <= N; n++) {
x[0][0] = 1;
for (int k = 1; k <= K; k++) {
int e = S[n-1];
for (int s = 0; s < e; s++) x[k][s] = y[k][s];
for (int s = 0; s <= maxsum-e; s++) {
x[k][s+e] = y[k-1][s] + y[k][s+e];
}
}
int[][] t = x;
x = y;
y = t;
}
// sum of unique K-subset sums
int sum = 0;
for (int s = minsum; s <= maxsum; s++) {
if (y[K][s] == 1) sum += s;
}
System.out.println(sum);
}
}
extern crate ndarray;
use ndarray::prelude::*;
use std::mem;
fn main() {
let numbers: Vec<i32> = (1..101).map(|x| x * x).collect();
let deg: usize = 50;
let mut min_sum: usize = 0;
for i in 0..deg {
min_sum += numbers[i] as usize;
}
let mut max_sum: usize = 0;
for i in deg..numbers.len() {
max_sum += numbers[i] as usize;
}
// Make an array
let mut x = OwnedArray::from_elem((deg + 1, max_sum + 1), 0i32);
let mut y = OwnedArray::from_elem((deg + 1, max_sum + 1), 0i32);
y[(0, 0)] = 1;
for n in 1..numbers.len() + 1 {
x[(0, 0)] = 1;
println!("Completed step {} out of {}", n, numbers.len());
for k in 1..deg + 1 {
let e = numbers[n - 1] as usize;
for s in 0..e {
x[(k, s)] = y[(k, s)];
}
for s in 0..max_sum - e + 1 {
x[(k, s + e)] = y[(k - 1, s)] + y[(k, s + e)];
}
}
mem::swap(&mut x, &mut y);
}
let mut ans = 0;
for s in min_sum..max_sum + 1 {
if y[(deg, s)] == 1 {
ans += s;
}
}
println!("{}", ans);
}
To diagnose a performance issue in general, I:
Get a baseline time or rate. Preferably create a testcase that only takes a few seconds, as profilers tend to slow down the system a bit. You will also want to iterate frequently.
Compile in release mode with debugging symbols.
Run the code in a profiler. I'm on OS X so my main choice is Instruments, but I also use valgrind.
Find the hottest code path, think about why it's slow, try something, measure.
The last step is the hard part.
In your case, you have a separate implementation that you can use as your baseline. Comparing the two implementations, we can see that your data structures differ. In Java, you are building nested arrays, but in Rust you are using the ndarray crate. I know that crate has a good maintainer, but I personally don't know anything about the internals of it, or what use cases it best fits.
So I rewrote it with using the standard-library Vec.
The other thing I know is that direct array access isn't as fast as using an iterator. This is because array access needs to perform a bounds check, while iterators bake the bounds check into themselves. Many times this means using methods on Iterator.
The other change is to perform bulk data transfer when you can. Instead of copying element-by-element, move whole slices around, using methods like copy_from_slice.
With those changes the code looks like this (apologies for poor variable names, I'm sure you can come up with semantic names for them):
use std::mem;
const N: usize = 100;
const DEGREE: usize = 50;
fn main() {
let numbers: Vec<_> = (1..N+1).map(|v| v*v).collect();
let min_sum = numbers[..DEGREE].iter().fold(0, |a, &v| a + v as usize);
let max_sum = numbers[DEGREE..].iter().fold(0, |a, &v| a + v as usize);
// different data types for x and y!
let mut x = vec![vec![0; max_sum+1]; DEGREE+1];
let mut y = vec![vec![0; max_sum+1]; DEGREE+1];
y[0][0] = 1;
for &e in &numbers {
let e2 = max_sum - e + 1;
let e3 = e + e2;
x[0][0] = 1;
for k in 0..DEGREE {
let current_x = &mut x[k+1];
let prev_y = &y[k];
let current_y = &y[k+1];
// bulk copy
current_x[0..e].copy_from_slice(¤t_y[0..e]);
// more bulk copy
current_x[e..e3].copy_from_slice(&prev_y[0..e2]);
// avoid array index
for (x, y) in current_x[e..e3].iter_mut().zip(¤t_y[e..e3]) {
*x += *y;
}
}
mem::swap(&mut x, &mut y);
}
let sum = y[DEGREE][min_sum..max_sum+1].iter().enumerate().filter(|&(_, &v)| v == 1).fold(0, |a, (i, _)| a + i + min_sum);
println!("{}", sum);
println!("{}", sum == 115039000);
}
2.060s - Rust 1.9.0
2.225s - Java 1.7.0_45-b18
On OS X 10.11.5 with a 2.3 GHz Intel Core i7.
I'm not experienced enough with Java to know what kinds of optimizations it can do automatically.
The biggest potential next step I see is to leverage SIMD instructions when performing the addition; it's pretty much exactly what SIMD is made for.
As pointed out by Eli Friedman, avoiding array indexing by zipping isn't currently the most performant way of doing this.
With the changes below, the time is now 1.267s.
let xx = &mut current_x[e..e3];
xx.copy_from_slice(&prev_y[0..e2]);
let yy = ¤t_y[e..e3];
for i in 0..(e3-e) {
xx[i] += yy[i];
}
This generates assembly that appears to unroll the loop as well as using SIMD instructions:
+0x9b0 movdqu -48(%rsi), %xmm0
+0x9b5 movdqu -48(%rcx), %xmm1
+0x9ba paddd %xmm0, %xmm1
+0x9be movdqu %xmm1, -48(%rsi)
+0x9c3 movdqu -32(%rsi), %xmm0
+0x9c8 movdqu -32(%rcx), %xmm1
+0x9cd paddd %xmm0, %xmm1
+0x9d1 movdqu %xmm1, -32(%rsi)
+0x9d6 movdqu -16(%rsi), %xmm0
+0x9db movdqu -16(%rcx), %xmm1
+0x9e0 paddd %xmm0, %xmm1
+0x9e4 movdqu %xmm1, -16(%rsi)
+0x9e9 movdqu (%rsi), %xmm0
+0x9ed movdqu (%rcx), %xmm1
+0x9f1 paddd %xmm0, %xmm1
+0x9f5 movdqu %xmm1, (%rsi)
+0x9f9 addq $64, %rcx
+0x9fd addq $64, %rsi
+0xa01 addq $-16, %rdx
+0xa05 jne "slow::main+0x9b0"
I'm trying to convert some Octave functions to Java, but I'm not sure I'm this right.
function [y,a] = forwardProp(x, Thetas)
a{1} = x;
L = length(Thetas)+1;
for i = 2:L,
a{i-1} =[1; a{i-1}];
z{i} =Thetas{i-1}*a{i-1};
a{i} =sigmoid(z{i});
end
y = a{L};
end
My Java Function
public class ForwardProp {
public static DoubleMatrix ForwardProp(DoubleMatrix x, DoubleMatrix Thetas)
{
DoubleMatrix a = new DoubleMatrix();
a = DoubleMatrix.concatHorizontally(DoubleMatrix.ones(a.rows, 1), x);
int L = Thetas.length + 1;
DoubleMatrix z = new DoubleMatrix();
for (int i = 2; i <= L; i++)
{
a.put(i - 1, a.get(i - 1));
z.put(i, (Thetas.get(-1) * a.get(i - 1)));
a.put(i, Sigmoid(z.get(i)));
}
return a;
}
}
Can someone tell me if this is right???
As far as I can tell, you are committing a double-fencepost error here:
int L = Thetas.length + 1;
L now equals 1 more than the number of elements in the matrix...
for (int i = 2; i <= L; i++) ...and you are now looping with Thetas.get(i - 1) all the way up to an index that is 2 greater than the highest index available from Thetas.get(int).
Remember, Thetas.get(int) directly accesses the internal array that stores this matrix's data. This can only accept indices from 0 to Thetas.length - 1. So when you call Thetas.get(-1) you will always get an error because -1 is not a valid array index; when you get to the end of the loop and call Thetas.get(i - 1), you will get an error again because there is no element at that location.
You are also initializing your output matrix with DoubleMatrix z = new DoubleMatrix();, which returns a 0x0 empty matrix with no elements. That's not what you want either.
Try to make sure you know which indices your data is in, then rewrite it when you know how to reference the data you are using.
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()