I'm working on a program that calculates pi based on randomly generated float numbers that represent x,y co-ordinates on a graph. Each x, y co-ordinate is raised by the power of 2 and stored in two separate arrays. The co-ordinates are distributed uniformly on a graph of interval of 0,1.
The program adds the x, y co-ordinates and if they are less than 1 then the points are located within a circle of diameter 1, illustrated in the diagram below.
I then used the formula,
π ≈ 4 w / n
to work out pi. Where, w is the count of the points within the circle and n is the number of x or y co-ordinates within the arrays.
When I set n up to 10,000,000 (the size of the array) it generates the most accurate calculation of pi of 15-16 decimal places. However after dedicating 4GB of RAM to the run config and setting n to 100,000,000 pi ends up being 0.6710...
I was wondering why this may be happening? Sorry if this is a stupid question.. code is below.
import java.text.DecimalFormat;
import java.util.Random;
public class random_pi {
public random_pi() {
float x2_store[] = new float[10000000];
float y2_store[] = new float[10000000];
float w = 0;
Random rand = new Random();
DecimalFormat df2 = new DecimalFormat("#,###,###");
for (int i = 0; i < x2_store.length; i++) {
float x2 = (float) Math.pow(rand.nextFloat(), 2);
x2_store[i] = x2;
float y2 = (float) Math.pow(rand.nextFloat(), 2);
y2_store[i] = y2;
}
for (int i = 0; i < x2_store.length; i++) {
if (x2_store[i] + y2_store[i] < 1) {
w++;
}
}
System.out.println("w: "+w);
float numerator = (4*w);
System.out.printf("4*w: " + (numerator));
System.out.println("\nn: " + df2.format(x2_store.length));
float pi = numerator / x2_store.length;
String fmt = String.format("%.20f", pi);
System.out.println(fmt);
String pi_string = Double.toString(Math.abs(pi));
int intP = pi_string.indexOf('.');
int decP = pi_string.length() - intP - 1;
System.out.println("decimal places: " + decP);
}
public static void main(String[] args) {
new random_pi();
}
}
The problem is here:
float w = 0;
float numerator = (4*w);
float precision is not enough, change it to int or double:
Like this working sample code:
import java.text.DecimalFormat;
import java.util.Random;
public class random_pi {
public random_pi() {
float x2_store[] = new float[100000000];
float y2_store[] = new float[100000000];
int w = 0;
Random rand = new Random();
DecimalFormat df2 = new DecimalFormat("#,###,###");
for (int i = 0; i < x2_store.length; i++) {
float x2 = (float) Math.pow(rand.nextFloat(), 2);
x2_store[i] = x2;
float y2 = (float) Math.pow(rand.nextFloat(), 2);
y2_store[i] = y2;
}
for (int i = 0; i < x2_store.length; i++) {
if (x2_store[i] + y2_store[i] < 1) {
w++;
}
}
System.out.println("w: "+w);
int numerator = (4*w);
System.out.printf("4*w: " + (numerator));
System.out.println("\nn: " + df2.format(x2_store.length));
float pi = ((float)numerator) / x2_store.length;
String fmt = String.format("%.20f", pi);
System.out.println(fmt);
String pi_string = Double.toString(Math.abs(pi));
int intP = pi_string.indexOf('.');
int decP = pi_string.length() - intP - 1;
System.out.println("decimal places: " + decP);
}
public static void main(String[] args) {
new random_pi();
}
}
output:
w: 78544041
4*w: 314176164
n: 100,000,000
3.14176154136657700000
decimal places: 15
And you don't need to store the results, like this working sample code:
import java.text.DecimalFormat;
import java.util.Random;
public class pi {
public pi() {
double n=100000000;
double w = 0;
Random rand = new Random();
DecimalFormat df2 = new DecimalFormat("#,###,###");
for (int i = 0; i < n; i++) {
double x = rand.nextFloat();
double y = rand.nextFloat();
if ((x*x + y*y) < 1.0) w++;
}
System.out.println("w: "+w);//w: 7852372.0
double numerator = (4*w);
System.out.printf("4*w: " + (numerator));//4*w: 3.1409488E7
System.out.println("\nn: " + df2.format(n));//n: 10,000,000
double pi = numerator / n;
final String fmt = String.format("%.20f", pi);
System.out.println(fmt);//3.14094877243042000000
String pi_string = Double.toString(Math.abs(pi));
int intP = pi_string.indexOf('.');
int decP = pi_string.length() - intP - 1;
System.out.println("decimal places: " + decP);//decimal places: 14
}
public static void main(String[] args) {
new random_pi();
}
}
output:
w: 78539606
4*w: 314158424
n: 100,000,000
3.14158439636230470000
decimal places: 16
Related
I'm just playing with Android Studio bitmaps and have created a dotted background for my application through iteration.
constant = 60;
int padding_X = (int) Math.floor((width % constant)/2f);
if (padding_X == 0) {
padding_X = (int) Math.floor(constant / 2);
}
int padding_Y = (int) Math.floor((height % constant)/2f);
if (padding_Y == 0) {
padding_Y = (int) Math.floor(constant/2);
}
System.out.println("padding X: "+padding_X);
System.out.println("padding Y: "+padding_Y);
int max_xn = Math.round((width-(padding_X*2)) / constant);
int max_yn = Math.round((height-(padding_Y*2)) / constant);
System.out.println("max xn: "+max_xn);
System.out.println("max yn: "+max_yn);
point_matrix = new int[max_xn+1][max_yn+1][2];
lens = new int[2];
for (int yn = 0; yn <= max_yn; yn++) {
int y = (int) (padding_Y + (yn*constant));
for (int xn = 0; xn <= max_xn; xn++) {
int x = (int) (padding_X + (xn*constant));
System.out.println("point # x: "+x+" y: "+y);
canvas.setPixel(x,y,Color.parseColor("#ffffff"));
point_matrix[xn][yn][0] = x;
point_matrix[xn][yn][1] = y;
}
}
runOnUiThread(() -> {
iv0.setImageBitmap(canvas);
});
lens[0] = max_xn+1;
lens[1] = max_yn+1;
I have also added each white pixel to a 3 dimensional array int[][][]. The array holds xn and yn for indexing the dots. Last array holds the coordinates onscreen. Example: {5, 1, {100,250}} 5 is the dots index on x axis, 1 is the index on y axis and 100 and 250 are coordinates on the bitmap.
I'm hoping to find a way for finding all dots on the 3 dim. array on a certain radius from the center.
A plan I had was iterating through all elements in the 3dim array and calculating the distance to the center with pythagoras theorem or something like that but that would be really inefficient seeing as this would have to be done multiple times.
The final plan is to have all of the dots to dissapear in a circular motion starting from the center. With a delay between each "radius interval".
Use trigonometric functions :)
static double i = 0;
static double pi = Math.PI;
static int q = 5; // half size of array
static double x;
static double y;
static double cx = 5; // offset center x
static double cy = 5; // offset center y
public static void main(String[] args) {
while (i < pi * 2) { // pi*2 is full angle of circle
x = Math.round (cx + Math.sin(i) * q);
y = Math.round (cy + Math.cos(i) * q);
System.out.print(String.format("X = %4f", x) + String.format("Y = %4f", y) + "\n");
i+=pi/180;
}
}
I make my first steps in implementation of batch and stochastic gradient descent.
Here is my implementation:
package ch.learning;
import java.util.*;
import org.jzy3d.analysis.AbstractAnalysis;
import org.jzy3d.analysis.AnalysisLauncher;
import org.jzy3d.chart.factories.AWTChartComponentFactory;
import org.jzy3d.colors.Color;
import org.jzy3d.colors.ColorMapper;
import org.jzy3d.colors.colormaps.ColorMapRainbow;
import org.jzy3d.maths.Coord3d;
import org.jzy3d.maths.Range;
import org.jzy3d.plot3d.builder.*;
import org.jzy3d.plot3d.builder.concrete.*;
import org.jzy3d.plot3d.primitives.Scatter;
import org.jzy3d.plot3d.primitives.Shape;
import org.jzy3d.plot3d.rendering.canvas.Quality;
import org.apache.commons.math3.analysis.function.Sigmoid;
public class LogisticReg_GradientDescent {
private List<double[]> trainingExamples = new LinkedList<double[]>();
private static final int sizeTrainingset = 1000;
private volatile double[] theta = {10, 10, 10, 10 };
// Configurable compoenent of step size during theata update
private final double alpha = 0.01;
// Amount of iteration in Batch Gradient Descent
private static final int iterations = 10000;
private static final int printsAtStartAndEnd = 5;
private void buildTrainingExample(int amount) {
// Area of the house
double areaMin = 80;
double areaMax = 1000;
double areaRange = areaMax - areaMin;
// Distance to center
double distanceMin = 10;
double distanceMax = 10000;
double distanceRange = distanceMax - distanceMin;
// Generate training examples with prices
for (int i = 0; i < amount; i++) {
double[] example = new double[5];
example[0] = 1.0;
example[1] = areaMin + Math.random() * areaRange;
example[2] = distanceMin + Math.random() * distanceRange;
// Price is a feature as well in this logistic regression example
double price = 0;
price += _priceComponent(example[1], areaRange);
price += _priceComponent(example[2], distanceRange);
// price += _priceComponent(example[3], yocRange);
example[3] = price;
example[4] = (price>200000)?0:1;
trainingExamples.add(example);
}
}
// Random price according with some range constraints
private double _priceComponent(double value, double range) {
if (value <= range / 3)
return 50000 + 50000 * Math.random() * 0.1;
if (value <= (range / 3 * 2))
return 100000 + 100000 * Math.random() * 0.1;
return 150000 + 150000 * Math.random() * 0.1;
}
private double classificationByHypothesis(double[] features) {
// Scaling
double scalingF0 = features[0];
double scalingF1 = (features[1] - 80) / (920);
double scalingF2 = (features[2] - 10) / (9990);
double scalingF3 = (features[3] - 50000) / (400000);
double z = this.theta[0] * scalingF0 + this.theta[1] * scalingF1 + this.theta[2] * scalingF2
+ this.theta[3] * scalingF3;
double ret = 1 / (1 + Math.pow(Math.E, -z));
return ret;
}
// Costfunction: Mean squared error function
private double gradientBatch_costs() {
double costs = this.trainingExamples.stream().mapToDouble(l -> {
double costsint;
if (l[4] == 0) {
costsint = -Math.log(1 - classificationByHypothesis(l));
} else {
costsint = -Math.log(classificationByHypothesis(l));
}
return costsint;
}).sum();
return costs / this.trainingExamples.size();
}
// Theta Update with Batch Gradient Descent
private void gradientBatch_thetaUpdate(int amount) {
for (int i = 0; i < amount; i++) {
double partialDerivative0 = this.trainingExamples.stream()
.mapToDouble(l -> (classificationByHypothesis(l) - l[4]) * l[0]).sum();
double tmpTheta0 = this.theta[0] - (this.alpha * partialDerivative0 / this.trainingExamples.size());
double partialDerivative1 = this.trainingExamples.stream()
.mapToDouble(l -> (classificationByHypothesis(l) - l[4]) * l[1]).sum();
double tmpTheta1 = this.theta[1] - (this.alpha * partialDerivative1 / this.trainingExamples.size());
double partialDerivative2 = this.trainingExamples.stream()
.mapToDouble(l -> (classificationByHypothesis(l) - l[4]) * l[2]).sum();
double tmpTheta2 = this.theta[2] - (this.alpha * partialDerivative2 / this.trainingExamples.size());
double partialDerivative3 = this.trainingExamples.stream()
.mapToDouble(l -> (classificationByHypothesis(l) - l[4]) * l[3]).sum();
double tmpTheta3 = this.theta[3] - (this.alpha * partialDerivative3 / this.trainingExamples.size());
this.theta = new double[] { tmpTheta0, tmpTheta1, tmpTheta2, tmpTheta3 };
}
}
// Theta update with Stochastic Gradient Descent
private void gradientStochastic_thetaUpdate(double[] feature) {
double tmpTheta0 = this.theta[0] - this.alpha * (classificationByHypothesis(feature) - feature[4]) * feature[0];
double tmpTheta1 = this.theta[1] - this.alpha * (classificationByHypothesis(feature) - feature[4]) * feature[1];
double tmpTheta2 = this.theta[2] - this.alpha * (classificationByHypothesis(feature) - feature[4]) * feature[2];
double tmpTheta3 = this.theta[3] - this.alpha * (classificationByHypothesis(feature) - feature[4]) * feature[3];
this.theta = new double[] { tmpTheta0, tmpTheta1, tmpTheta2, tmpTheta3 };
}
private void resetTheta() {
this.theta = new double[] {0.00001, 0.00001, 0.00001, 0.00001};
}
private void printSummary(int iteration) {
System.out.println(String.format("%s \t\t Theta: %f \t %f \t %f \t %f \t Costs: %f", iteration, this.theta[0],
this.theta[1], this.theta[2], this.theta[3], this.gradientBatch_costs()));
}
public static void main(String[] args) {
LogisticReg_GradientDescent d = new LogisticReg_GradientDescent();
// Batch and Stochastic Gradient Descent use the same training example
d.buildTrainingExample(sizeTrainingset);
System.out.println("Batch Gradient Descent");
d.printSummary(0);
System.out.println(String.format("First %s iterations", printsAtStartAndEnd));
for (int i = 1; i <= iterations; i++) {
d.gradientBatch_thetaUpdate(1);
d.printSummary(i);
}
System.out.println("Some examples are:");
System.out.println(String.format("The 1:%s, Area:%s, Distance:%s, Price:%s, Classification:%s", d.trainingExamples.get(0)[0],d.trainingExamples.get(0)[1],d.trainingExamples.get(0)[2],d.trainingExamples.get(0)[3],d.trainingExamples.get(0)[4]));
System.out.println(String.format("The 1:%s, Area:%s, Distance:%s, Price:%s, Classification:%s", d.trainingExamples.get(500)[0],d.trainingExamples.get(500)[1],d.trainingExamples.get(500)[2],d.trainingExamples.get(500)[3],d.trainingExamples.get(500)[4]));
try {
AnalysisLauncher.open(d.new SurfaceDemo());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
class SurfaceDemo extends AbstractAnalysis{
#Override
public void init(){
double x;
double y;
double z;
float a;
Coord3d[] points = new Coord3d[trainingExamples.size()];
Color[] colors = new Color[trainingExamples.size()];
for(int i=0; i<trainingExamples.size(); i++){
x = trainingExamples.get(i)[1]; // Area
y = trainingExamples.get(i)[2]; // Distance to center
z = trainingExamples.get(i)[3]; // price
points[i] = new Coord3d(x, y, z);
a = 1f;
if(trainingExamples.get(i)[4]==1){
colors[i] =new Color(0,0,0,a);
}else{
colors[i]= new Color(250,0,0,a);
}
}
Scatter scatter = new Scatter(points, colors);
scatter.setWidth(4);
Mapper mapper = new Mapper() {
#Override
public double f(double x, double y) {
return (-theta[0]-theta[1]*x-theta[2]*y)/theta[3];
}
};
// Create the object to represent the function over the given range.
Range rangeX = new Range(0, 1000);
Range rangeY = new Range(0, 10000);
int steps = 10;
final Shape surface = Builder.buildOrthonormal(new OrthonormalGrid(rangeX, steps, rangeY, steps), mapper);
surface.setColorMapper(new ColorMapper(new ColorMapRainbow(), surface.getBounds().getZmin(), surface.getBounds().getZmax(), new Color(1, 1, 1, .5f)));
surface.setFaceDisplayed(true);
surface.setWireframeDisplayed(false);
chart = AWTChartComponentFactory.chart(Quality.Advanced, getCanvasType());
chart.getScene().add(scatter);
chart.getScene().add(surface);
}
}
}
A graphical representation looks like
So i plot the generated training instances with org.jzy3d.plot3d.
We see x(the area of the house), y(distance to town center) and z(price).
The classification makes red (negative class -> not sold) and black (positive class -> sold).
In the generated trainings instances the classification depends just at the price, you see it here:
example[4] = (price>200000)?0:1;
The problem, the thing I don't understand is
I would like to plot the decision boundary of my classificator.
The decision bounday depends on the optimized components from Theta. (Using batch gradient descent).
So i try to plot the decision boundary plane with this code:
Mapper mapper = new Mapper() {
#Override
public double f(double x, double y) {
return (-theta[0]-theta[1]*x-theta[2]*y)/theta[3];
}
};
Because
theta[0]*1 + theta[1 ]*x + theta[2]*y + theta[3]*z = 0
so
z = -(theta[0]*1 + theta[1 ]*x + theta[2]*y)/theta[3]
I would expect my decision boundary plane between the red- and blackarea.
Instead it hangs around by z=0.
I didn't know, either I'm not able to plot this decision boundary plane in a proper way, or my optimized parameters are shit.
Further I don't know how to choose a good initial theta vector.
Right now i use
private volatile double[] theta = {1, 1, 1, 1 };
I set alpha to 0.0001
private final double alpha = 0.0001;
It was the biggest possible Alpha, where my cost function doesn't jump around and the sigmoid implementation doesn't return infinity.
I already make feature scaling at
private double classificationByHypothesis(double[] features) {
// Scaling
double scalingF0 = features[0];
double scalingF1 = (features[1] - 80) / (920);
double scalingF2 = (features[2] - 10) / (9990);
double scalingF3 = (features[3] - 50000) / (400000);
double z = this.theta[0] * scalingF0 + this.theta[1] * scalingF1 + this.theta[2] * scalingF2
+ this.theta[3] * scalingF3;
double ret = 1 / (1 + Math.pow(Math.E, -z));
return ret;
}
The last five iteration with given initial theta and alpha equals 0.0001 are
9996,Theta: 1.057554,-6.340981,-6.242139,8.145087,Costs: 0.359108
9997,Theta: 1.057560,-6.341234,-6.242345,8.145576,Costs: 0.359109
9998,Theta: 1.057565,-6.341487,-6.242552,8.146065,Costs: 0.359110
9999,Theta: 1.057571,-6.341740,-6.242758,8.146553,Costs: 0.359112
10000,Theta: 1.057576,-6.341993,-6.242965,8.147042,Costs: 0.359113
Some example of the generated training instances are
Area: 431.50139030510206, Distance: 8591.341686012887,
Price: 255049.1280388437, Classification:0.0
Area: 727.4042972310916, Distance: 4364.710136408952,
Price: 258385.59452489938, Classification:0.0
Thanks for any hint!
//I'm trying to draw a new dot every 250 milliseconds but it only draws the dot a single time. I have tried fixing it many times, but it still will only paint a single dot, rather than one after 250 milliseconds. Is this a problem with the timer or the paint method? Here is the code:
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Window extends JPanel{
private int size;
private static double maxValue;
private double elevation;
private double vertV;
public double horizV;
public double gravity;
public double range;
public double time;
public double t = 0;
public Window(int s, double v, double e, double v2, double g,double h,double r,double t){
size = s;
maxValue = v;
elevation = e;
vertV = v2;
gravity = g;
horizV = h;
range = r;
time = t;
setPreferredSize(new Dimension(size, size));
}
public void paintComponent(Graphics g){
g.drawLine(size/25, 0,size/25, size);
g.drawLine(0, size - (size/25), size, size - (size/25));
double[] lines = getLine();
int x = size/5 + (size/25), y = size - (size/25);
int x2 = x;
for(int i = 0; i < 4; i++){
g.drawLine(x, y+5, x, y-5);
g.drawString(lines[i]+"",x-size/50,y+size/30);
x+=x2;
}
int yx = size/25, yy = size - (size/5 + (size/25));
int y2 = size/5 + (size/25);
for(int i=0;i<4;i++){
g.drawLine(yx-5, yy, yx+5, yy);
g.drawString(lines[i]+"",yx-size/25,yy+size/30);
yy -= y2;
}
drawDots(g);
}
//this is the place where i make the dots but it only makes one.
//used to be a for loop but i altered it to an if statement so i could paint one dot at a time
public void drawDots(Graphics g)
{
double ratio = (size-((size/25)*2))/maxValue;
double fx;
double xvalue;
// This for loop is where dots are drawn, each iteration draws one dot. It starts at zero, and counts up to the time variable t.
if(t<=time)
{
t+=0.025;
t = Math.round(t*1000.0)/1000.0;
fx = function(t);
xvalue = xfunction(t);
if(fx >= 0){
System.out.print("Time: " + t + " " + "Range: " + xvalue + " " + "Height: ");
System.out.println(fx);
g.drawLine((int)(size/25+(ratio*xvalue)), (int)((size-(size/25))-(ratio*fx)),
(int)(size/25+(ratio*xvalue)), (int)((size-(size/25))-(ratio*fx)));
}
}
}
//where i make the timer
//250 mill
public void dostuff()
{
int delay = 250;
ActionListener taskPerformer = new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
repaint();
}
};
new Timer(delay, taskPerformer).start();
}
public double xfunction(double t){
double x = 0.0;
x = Math.round(horizV * t * 1000.0)/1000.0;
return x;
}
public double function(double t){
double fx = 0.0;
fx = Math.round((vertV*t + .5*(-(gravity))*(t*t) + elevation)*1000.0)/1000.0;
return fx;
}
private static double[] getLine(){
double increment = maxValue / 4;
double currentLine = 0;
double[] lines = new double[4];
for(int i = 0; i < 4; i++){
currentLine+=increment;
lines[i] = Math.round(currentLine * 10.0)/10.0;
}
return lines;
}
}
This is the original version of the code that displays the projectile's motion, but it does not wait 250 milliseconds between drawing each point:
import javax.swing.JPanel;
import java.awt.*;
public class Window extends JPanel{
private int size;
private static double maxValue;
private double elevation;
private double vertV;
public double horizV;
public double gravity;
public double range;
public double time;
public Window(int s, double v, double e, double v2, double g,double h,double r,double t){
size = s;
maxValue = v;
elevation = e;
vertV = v2;
gravity = g;
horizV = h;
range = r;
time = t;
setPreferredSize(new Dimension(size, size));
}
public void paintComponent(Graphics g){
g.drawLine(size/25, 0,size/25, size);
g.drawLine(0, size - (size/25), size, size - (size/25));
double[] lines = getLine();
int x = size/5 + (size/25), y = size - (size/25);
int x2 = x;
for(int i = 0; i < 4; i++){
g.drawLine(x, y+5, x, y-5);
g.drawString(lines[i]+"",x-size/50,y+size/30);
x+=x2;
}
int yx = size/25, yy = size - (size/5 + (size/25));
int y2 = size/5 + (size/25);
for(int i=0;i<4;i++){
g.drawLine(yx-5, yy, yx+5, yy);
g.drawString(lines[i]+"",yx-size/25,yy+size/30);
yy -= y2;
}
drawDots(g);
}
public void drawDots(Graphics g){
double ratio = (size-((size/25)*2))/maxValue;
double fx;
double xvalue;
// This for loop is where dots are drawn, each iteration draws one dot. It starts at zero, and counts up to the time variable t.
for(double t=0;t<=time; t+=0.025){
t = Math.round(t*1000.0)/1000.0;
fx = function(t);
xvalue = xfunction(t);
if(fx >= 0){
System.out.print("Time: " + t + " " + "Range: " + xvalue + " " + "Height: ");
System.out.println(fx);
g.drawLine((int)(size/25+(ratio*xvalue)), (int)((size-(size/25))-(ratio*fx)),
(int)(size/25+(ratio*xvalue)), (int)((size-(size/25))-(ratio*fx)));
}
}
}
public double xfunction(double t){
double x = 0.0;
x = Math.round(horizV * t * 1000.0)/1000.0;
return x;
}
public double function(double t){
double fx = 0.0;
fx = Math.round((vertV*t + .5*(-(gravity))*(t*t) + elevation)*1000.0)/1000.0;
return fx;
}
private static double[] getLine(){
double increment = maxValue / 4;
double currentLine = 0;
double[] lines = new double[4];
for(int i = 0; i < 4; i++){
currentLine+=increment;
lines[i] = Math.round(currentLine * 10.0)/10.0;
}
return lines;
}
}
I've been trying to implement a perlin noise generator in java, based on this article. Homever, my generator produces noise that is not continuous but instead "blocky", forming visible lines between every even numbered -coordinate. Below is my current code:
private static final Point[] grads = {
new Point(1, 0), new Point(-1, 0), new Point(0, 1), new Point(0, -1),
new Point(1, 1), new Point(1, -1), new Point(-1, 1), new Point(-1, -1)
};
private int permutations[] = new int[512];
private int frequency;
private int seed;
private double[][] heightMap;
private double amplitude;
public PerlinNoise(int frequency, int seed, double[][] heightMap, double amplitude) {
this.frequency = frequency;
this.seed = seed; //Seed for randomizing the permutation table
this.heightMap = heightMap; //The Heightmap where the finalt result will be stored
this.amplitude = amplitude;
}
private void seedPermutationTables() {
LinkedList<PermutationValue> l = new LinkedList<PermutationValue>();
Random rand = new Random(this.seed);
for (int i = 0; i < 256; i++) {
l.add(new PermutationValue(i, rand));
}
Collections.sort(l);
for (int i = 0; i < 512; i++) {
permutations[i] = l.get(i & 255).getValue();
}
}
public void generateNoise() {
this.seedPermutationTables();
int sWidth = this.heightMap.length / frequency;
int sHeight = this.heightMap[0].length / frequency;
for (int i = 0; i < this.heightMap.length; i++) {
for (int j = 0; j < this.heightMap[i].length; j++) {
double x = (double)i / sWidth;
double y = (double)j / sHeight;
this.heightMap[i][j] = this.noise(x, y);
}
}
}
private double noise(double x, double y) {
int xi = (int)x & 255;
int yi = (int)y & 255;
double xf = x - (int)x;
double yf = y - (int)y;
double u = this.fade(xf);
double v = this.fade(yf);
int aa = permutations[permutations[xi] + yi];
int ab = permutations[permutations[xi] + yi + 1];
int ba = permutations[permutations[xi + 1] + yi];
int bb = permutations[permutations[xi + 1] + yi + 1];
double x1 = this.lerp(this.grad(aa, xf, yf), this.grad(ab, xf - 1, yf), u);
double x2 = this.lerp(this.grad(ba, xf, yf - 1), this.grad(bb, xf - 1, yf - 1), u);
double noise = this.lerp(x1, x2, v);
return (1D + noise) / 2 * this.amplitude; //The noise returns values between -1 and 1
//So we change the range to 0-amplitude
}
private double grad(int hash, double x, double y) {
hash = hash & 7;
Point p = grads[hash];
return p.x * x + p.y * y;
}
private double lerp(double a, double b, double x) {
return a + x * (b - a);
}
private double fade(double x) {
return x * x * x * (x * (x * 6 - 15) + 10);
}
private class PermutationValue implements Comparable<PermutationValue> {
private int value;
private double sortValue;
public PermutationValue(int value, Random rand) {
this.setValue(value);
this.sortValue = rand.nextDouble();
}
#Override
public int compareTo(PermutationValue pv) {
if (pv.sortValue > this.sortValue) {
return -1;
}
return 1;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
The heightmap array simply stores the height value for every pixel. Any suggestions or ideas what might be causing these formations?
hash tables can be replaced with 1-2 multiplications as in rndng fct:
blocky can come from lack of cubic interpolation or digital noise from the hash table.
in your case it sounds like it's not lerping between two values of the hash table. lerp just takes any 2 values and smooths between them. so if that's not running ok, it's blocky.
function rndng ( n: float ): float //total noise pseudo
{//random proportion -1, 1
var e = ( n *321.9)%1;
return (e*e*111.0)%2-1;
}
function lerps(o:float, v:float, alpha:float):float
{
o += ( v - o ) * alpha;
return o;
}
function lnz ( vtx: Vector3 ): float//3d noise
{
vtx= Vector3 ( Mathf.Abs(vtx.x) , Mathf.Abs(vtx.y) , Mathf.Abs(vtx.z) ) ;
var I = Vector3 (Mathf.Floor(vtx.x),Mathf.Floor(vtx.y),Mathf.Floor(vtx.z));
var D = Vector3(vtx.x%1,vtx.y%1,vtx.z%1);
D = Vector3(D.x*D.x*(3.0-2.0*D.x),D.y*D.y*(3.0-2.0*D.y),D.z*D.z*(3.0-2.0*D.z));
var W = I.x + I.y*71.0 + 125.0*I.z;
return lerps(
lerps( lerps(rndng(W+0.0),rndng(W+1.0),D.x) , lerps(rndng(W+71.0),rndng(W+72.0),D.x) , D.y)
,
lerps( lerps(rndng(W+125.0),rndng(W+126.0),D.x) , lerps(rndng(W+153.0),rndng(W+154.0),D.x) , D.y)
,
D.z
);
}
function lnzo ( vtx: Vector3 ): float
{
var total = 0.0;
for (var i:int = 1; i < 5; i ++)
{
total+= lnz2(Vector3 (vtx.x*(i*i),0.0,vtx.z*(i*i)))/(i*i);
}
return total*5;
}
function lnzh ( vtx: Vector3 ): float//3 axis 3d noise
{
vtx= Vector3 ( Mathf.Abs(vtx.z) , Mathf.Abs(vtx.z*.5-vtx.x*.866) , Mathf.Abs(vtx.z*.5+vtx.x*.866) ) ;
var I = Vector3 (Mathf.Floor(vtx.x),Mathf.Floor(vtx.y),Mathf.Floor(vtx.z));
var D = Vector3(vtx.x%1,vtx.y%1,vtx.z%1);
//D = Vector3(D.x*D.x*(3.0-2.0*D.x),D.y*D.y*(3.0-2.0*D.y),D.z*D.z*(3.0-2.0*D.z));
var W = I.x + I.y*71.0 + 125.0*I.z;
return lerps(
lerps( lerps(rndng(W+0.0),rndng(W+1.0),D.x) , lerps(rndng(W+71.0),rndng(W+72.0),D.x) , D.y)
,
lerps( lerps(rndng(W+125.0),rndng(W+126.0),D.x) , lerps(rndng(W+153.0),rndng(W+154.0),D.x) , D.y)
,
D.z
);
}
function lnz2 ( vtx: Vector3 ): float//2d noise
{
vtx= Vector3 ( Mathf.Abs(vtx.x) , Mathf.Abs(vtx.y) , Mathf.Abs(vtx.z) ) ;
var I = Vector3 (Mathf.Floor(vtx.x),Mathf.Floor(vtx.y),Mathf.Floor(vtx.z));
var D = Vector3(vtx.x%1,vtx.y%1,vtx.z%1);
D = Vector3(D.x*D.x*(3.0-2.0*D.x),D.y*D.y*(3.0-2.0*D.y),D.z*D.z*(3.0-2.0*D.z));
var W = I.x + I.y*71.0 + 125.0*I.z;
return lerps(
lerps( lerps(rndng(W+0.0),rndng(W+1.0),D.x) , lerps(rndng(W+71.0),rndng(W+72.0),D.x) , D.z)
,
lerps( rndng(W+125.0), rndng(W+126.0),D.x)
,
D.z
);
}
As the title suggests, I'm working on a homework assignment where we are limited to using multi-dimensional arrays in order to create a program that finds two points nearest to each other in a three dimensional space. So far my code looks like this (hybridized from examples in my textbook and my own code):
package exercise7_7;
public class Exercise7_7 {
public static void main(String[] args) {
java.util.Scanner input = new java.util.Scanner(System.in);
System.out.println("Enter the number of points:");
int numberOfPoints = input.nextInt();
double[][] points = new double[numberOfPoints][3];
System.out.println("Enter " + numberOfPoints + " points:");
for (int i = 0; i < points.length; i++) {
points[i][0] = input.nextDouble();
points[i][1] = input.nextDouble();
points[i][2] = input.nextDouble();
}
int p1 = 0, p2 = 1, p3 = 2;
double shortestDistance = distance(points[p1][0] , points[p1][1] , points[p1][2] ,
points[p2][0] , points[p2][1] , points[p2][2]);
for (int i = 0; i < points.length; i++) {
for (int j = i + 1; j < points.length; j++) {
double distance = distance(points[i][0] , points[j][0] , points[j][1] , points[j][2] , points[i][2] , points[j][2]);
if (shortestDistance > distance) {
p1 = i;
p2 = j;
shortestDistance = distance;
}
}
}
System.out.println("The closest two points are " + "(" + points[p1][0] + "," + points[p1][1] +
and (" + points[p2][0] + "," );
}
public static double distance(
double x1, double y1, double z1, double x2, double y2, double z2) {
return Math.sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)) + ((z2 - z1) * (z2 - z1)));
}
}
What I mostly need help with is figuring out just how to get these points compared. I don't think the way I tackled this problem was the best way to do it.
Thanks for the help guys. I'm running on 2 hours of sleep for 2 days now so please excuse any stupid questions or sloppy code.
******
I think I've got it:
package exercise7_7;
public class Exercise7_7 {
public static void main(String[] args) {
java.util.Scanner input = new java.util.Scanner(System.in);
System.out.println("Enter the number of points:");
int numberOfPoints = input.nextInt();
double[][] points = new double[numberOfPoints][3];
System.out.println("Enter " + numberOfPoints + " points:");
for (int i = 0; i < points.length; i++) {
points[i][0] = input.nextDouble();
points[i][1] = input.nextDouble();
points[i][2] = input.nextDouble();
}
int p1 = 0, p2 = 1;
double shortestDistance = distance(points[p1][0] , points[p1][1] , points[p1][2] ,
points[p2][0] , points[p2][1] , points[p2][2]);
for (int i = 0; i < points.length; i++) {
for (int j = i + 1; j < points.length; j++) {
double distance = distance(points[i][0] , points[j][0] , points[j][1] , points[j][2] , points[i][2] , points[j][2]);
if (shortestDistance > distance) {
p1 = i;
p2 = j;
shortestDistance = distance;
}
}
}
System.out.println("The closest two points are " + "(" + points[p1][0] + "," + points[p1][1] + "," + points[p1][2] +
") and (" + points[p2][0] + "," + points[p2][1] + "," + points[p2][2] + ")");
}
public static double distance(
double x1, double y1, double z1, double x2, double y2, double z2) {
return Math.sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)) + ((z2 - z1) * (z2 - z1)));
}
}
Input is taken in, processed, and then outputs the two closest points. Just as a reference, when:
(-1,0,3),(-1,-1,-1),(4,1,1),(2,0.5,9),(3.5,1.5,3),(-1.5,4,2),(5.5,4,-0.5) are inputted, the outcome
seems to be (-1,0,3) and (4,1,1). Could someone confirm that for me.
If this isn't the way to follow up on my own question, I apologize. First day on these slopes and I'm still
learning the ropes.
Use a class to represent your points. This way to you have a distanceTo method that calculates and returns distance. Also you can have a toString method that prints out the point for display to the user. Taking your code rearranging yields this class:
public class ThreeDPoint {
final double x;
final double y;
final double z;
public ThreeDPoint(final double x, final double y, final double z) {
this.x = x;
this.y = y;
this.z = z;
}
public double distanceto(final ThreeDPoint other) {
final double dx = other.x - x;
final double dy = other.y - y;
final double dz = other.z - z;
return Math.sqrt(dx * dx + dy * dy + dz * dz);
}
#Override
public String toString() {
return "{X=" + x + ",Y=" + y + ",Z=" + z + "}";
}
}
Now putting that together gives this, which is much more readable. I have removed the bit where you read points and used random numbers:
public static void main(String args[]) {
final ThreeDPoint[] points = new ThreeDPoint[5];
final Random random = new Random();
for (int i = 0; i < points.length; ++i) {
points[i] = new ThreeDPoint(random.nextInt(100), random.nextInt(100), random.nextInt(100));
}
//store min
double min = Double.POSITIVE_INFINITY;
int first = -1;
int last = -1;
for (int i = 0; i < points.length; ++i) {
for (int j = i + 1; j < points.length; ++j) {
final double d = points[i].distanceto(points[j]);
if (d < min) {
min = d;
first = i;
last = j;
}
}
}
System.out.println("The minimum distance is between point " + first + " and " + last + "(" + points[first] + " and " + points[last] + "). This distance is " + min + ".");
}
private static final class ThreeDPoint {
final double x;
final double y;
final double z;
public ThreeDPoint(final double x, final double y, final double z) {
this.x = x;
this.y = y;
this.z = z;
}
public double distanceto(final ThreeDPoint other) {
final double dx = other.x - x;
final double dy = other.y - y;
final double dz = other.z - z;
return Math.sqrt(dx * dx + dy * dy + dz * dz);
}
#Override
public String toString() {
return "{X=" + x + ",Y=" + y + ",Z=" + z + "}";
}
}