I wanted to make a Java app that calculates the square root using the Heron algorithm. But when I enter 9 it prints 2.777777910232544 to the screen.
When I enter 1 it prints 1. Now I do not know if I wrote the wrong code or I don't know something about floats in Java.
Here is my code:
public class MainActivity extends AppCompatActivity {
float length1;
float width1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView mainOutput = (TextView) findViewById(R.id.mainOutput);
final EditText mainInput = (EditText) findViewById(R.id.mainInput);
final Button wurzel2 = (Button) findViewById(R.id.wurzel2);
assert wurzel2 != null;
wurzel2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for(int i = 0; i < 20; i++) {
float inputNumber = Integer.parseInt(mainInput.getText().toString());
length1 = 1;
width1 = inputNumber / length1;
float length2 = (length1 + width1) / 2;
float width2 = inputNumber / length2;
length1 = length2;
width1 = width2;
}
double wurzel = length1 / width1;
mainOutput.setText(String.valueOf(wurzel));
}
});
}
}
I wrote a non-Android Java implementation of Heron's algorithm derived from the formula for the algorithm displayed at https://en.wikipedia.org/wiki/Methods_of_computing_square_roots
public class MyClass {
public static void main(String[] args) {
float x = 9;
System.out.println(heron(x));
}
static float heron(float s) {
float x = (float) 1.0; // initial approximation of result
for (int i = 0; i < 20; i++) {
float sDivX = s / x;
x = (x + sDivX) / 2;
// remove this line in production, this is just to watch progress
System.out.println(String.valueOf(x));
}
return x;
}
}
Your code had length1=1 (your length1 is equivalent to my x) inside the loop, so
it made no progress from iteration to iteration.
x = s/(float)2 might be a better initial estimate than 1, especially for larger values. 20 iterations is probably overkill for smallish values of the input value.
Related
This is the code I have done so far. It creates the ArrayList and adds the circles. The volume is stored and is printed in the console. The last thing I have to do is print out the smallest volume using a for-each loop. This is where I'm having difficulties. I could really use some help/advice
public static void main(String[] args)
{
Random rand = new Random();
final int RADIUS_MAX = 100;
int NUM_SPHERES = 4;
List<Sphere> spheres = new ArrayList<Sphere>();
for(int add = 1; add <= NUM_SPHERES; add++) {
spheres.add(new Sphere(rand.nextInt(RADIUS_MAX)));
}
for (Sphere s : spheres) {
System.out.println(s);
}
//TODO: Convert to a for-each loop to find the volume of the smallest sphere
for (Sphere s : spheres) {
}
}
You do not need an additional loop. The sphere with the smallest radius will have the smallest volume. You could store the smallest volume so far (initialized to a very large volume) and update it in either of your existing loops. I believe the formula for volume is (4. / 3) * Math.PI * Math.pow(radius, 3).
The volume formula of the sphere depends from radius like V <=> R, so no need to calculate volume each time, because minimal voule will be with minimal radius.
public class Foo {
public static void main(String... args) {
Random rand = new Random();
final int maxRadius = 100;
final int totalSphere = 4;
List<Sphere> spheres = new ArrayList<>();
for (int i = 0; i < totalSphere; i++)
spheres.add(new Sphere(rand.nextInt(maxRadius)));
for (Sphere sphere : spheres)
System.out.println(sphere);
Sphere smallestSphere = spheres.get(0);
for (Sphere sphere : spheres)
if (smallestSphere == null || sphere.compareTo(smallestSphere) < 0)
smallestSphere = sphere;
System.out.println("smallest volume: " + smallestSphere.getVolume());
}
public static class Sphere implements Comparable<Sphere> {
private final int radius;
public Sphere(int radius) {
this.radius = radius;
}
public double getVolume() {
return (4. / 3) * Math.PI * Math.pow(radius, 3);
}
#Override
public String toString() {
return "radius: " + radius;
}
#Override
public int compareTo(Sphere sphere) {
return Integer.compare(radius, sphere.radius);
}
}
}
I am doing this project that simulates the solar system using java's stdDraw. I want to make the change where I can show the trace of the corn, because my ultimate goal is to make this corn fly in a heart shape and if I can draw out the trace of the corn I can present the heart. Right now I've been trying to do it, but it seems like the background image is blocking the trace. And if I comment out the background image, all of the planets will show their trace. I don't know what to do, help!!!
Here is the Object Class:
public class BodyExtreme{
public double xxPos;
public double yyPos;
public double xxVel;
public double yyVel;
public double mass;
public String imgFileName;
private static final double G = 6.67e-11;
public BodyExtreme(double xP, double yP, double xV, double yV, double m, String img){
xxPos = xP;
yyPos = yP;
xxVel = xV;
yyVel = yV;
mass = m;
imgFileName = img;
}
public BodyExtreme(BodyExtreme b){
xxPos = b.xxPos;
yyPos = b.yyPos;
xxVel = b.xxVel;
yyVel = b.yyVel;
mass = b.mass;
imgFileName = b.imgFileName;
}
public double calcDistance(BodyExtreme b) {
double dx = b.xxPos - this.xxPos;
double dy = b.yyPos - this.yyPos;
return Math.sqrt(dx * dx + dy * dy);
}
public double calcForceExertedBy(BodyExtreme b) {
if (this.calcDistance(b) == 0) {
return 0;
} else {
return (G * b.mass * this.mass)/(this.calcDistance(b) * this.calcDistance(b));
}
}
public double calcForceExertedByX(BodyExtreme b) {
return (this.calcForceExertedBy(b) * (b.xxPos - this.xxPos) / this.calcDistance(b));
}
public double calcForceExertedByY(BodyExtreme b) {
return (this.calcForceExertedBy(b) * (b.yyPos - this.yyPos) / this.calcDistance(b));
}
public double calcNetForceExertedByX(BodyExtreme[] b) {
int i = 0;
double sum = 0;
while (i < b.length) {
if (this.equals(b[i])) {
sum += 0;
i += 1;
} else {
sum = sum + this.calcForceExertedByX(b[i]);
i += 1;
}
} return sum;
}
public double calcNetForceExertedByY(BodyExtreme[] b) {
int i = 0;
double sum = 0;
while (i < b.length) {
if (this.equals(b[i])) {
sum += 0;
i += 1;
} else {
sum = sum + this.calcForceExertedByY(b[i]);
i += 1;
}
} return sum;
}
public void update(double dt, double fX, double fY) {
double ax = fX / this.mass;
double ay = fY / this.mass;
double vx = this.xxVel + dt * ax;
double vy = this.yyVel + dt * ay;
double px = this.xxPos + dt * vx;
double py = this.yyPos + dt * vy;
this.xxPos = px;
this.yyPos = py;
this.xxVel = vx;
this.yyVel = vy;
}
public void draw() {
StdDraw.picture(this.xxPos, this.yyPos, "images/" + this.imgFileName);
}
public void lonelyplanet_update1(){
this.xxPos = this.xxPos + 45000000;
this.yyPos = this.yyPos + 100000000;
this.draw();
}
}
Here is the Main method class:
import java.util.Scanner;
public class NBodyExtreme{
public static double readRadius(String name) {
In in = new In(name);
int NumPlanets = in.readInt();
double Size = in.readDouble();
return Size;
}
public static BodyExtreme[] readBodies(String name) {
In in = new In(name);
int NumPlanets = in.readInt();
double Size = in.readDouble();
BodyExtreme[] bodies = new BodyExtreme[NumPlanets];
int i = 0;
while (i < NumPlanets) {
bodies[i] = new BodyExtreme(in.readDouble(), in.readDouble(), in.readDouble(), in.readDouble(), in.readDouble(), in.readString());
i += 1;
}
return bodies;
}
public static void main(String[] args) {
double T = Double.parseDouble(args[0]); /** Stoping Time */
double dt = Double.parseDouble(args[1]); /** Time Step */
String filename = args[2];
BodyExtreme[] bodies = readBodies(filename); /** Array of Bodies */
double radius = readRadius(filename); /** Canvas Radius */
In in = new In(filename);
int NumPlanets = in.readInt(); /** Number of Planets */
String imageToDraw = "images/starfield.jpg"; /** Background */
StdDraw.enableDoubleBuffering();
StdDraw.setScale(-2*radius, 2*radius);
StdDraw.clear();
StdDraw.picture(0, 0, imageToDraw); /** Draw Initial Background */
StdDraw.show();
int k = 0;
while (k < NumPlanets-1) { /** Draw Planets */
bodies[k].draw();
k += 1;
}
StdDraw.enableDoubleBuffering();
double time = 0.0;
while (time < T) {
double[] xForces = new double[NumPlanets-1];
double[] yForces = new double[NumPlanets-1];
int i = 0;
while (i < NumPlanets-1) {
xForces[i] = bodies[i].calcNetForceExertedByX(bodies);
yForces[i] = bodies[i].calcNetForceExertedByY(bodies);
i += 1;
}
i = 0;
while (i < NumPlanets-1) {
bodies[i].update(dt, xForces[i], yForces[i]);
i += 1;
}
bodies[NumPlanets-1].lonelyplanet_update1();
bodies[NumPlanets-1].draw();
StdDraw.show();
StdDraw.picture(0, 0, imageToDraw);
int j = 0;
while (j < NumPlanets) {
bodies[j].draw();
j += 1;
}
StdDraw.show();
StdDraw.pause(10);
}
time += dt;
}
}
This is what happens when the trace of route is blocked with the background image:
This is what happens when the trace is not blocked, but I only want the corn's trace not to be blokcekd.
you have a flaw in your animation logic:
to animate your screen you have to
update the model (each element, eg. backgroud or bodY),
then draw each model by using StdDraw.picture(..) and
finally make that content visible (by using StdDraw.show();)
for each time step in your animation (while (time < T){..}) you have to do all three steps.
public static void main(String[] args) {
...
StdDraw.enableDoubleBuffering(); //it's enough to call this only once!
double time = 0.0;
while (time < T) {
//do all the update stuff first, as shown in your code above
//then draw ONCE the BackGround:
StdDraw.picture(0, 0, imageToDraw);
//then draw all the planets (yes, i missed one)
while (j < NumPlanets) {
bodies[j].draw();
j += 1;
}
//finally make all the previous drawing visible
StdDraw.show();
//wait a bit for the next animation step
StdDraw.pause(10);
time += dt;
}
}
Formula should have and output = 12,5 with entered parameters of: wind speed = 10, true wind angle = 60, boat speed = 4 In my case it outputs: 13.458620941319543
public class Direction extends Boat {
private double trueWindAngle = 60;
private double trueWindSpeed = 10;
private double apparentWindAngle;
private double apparentWindSpeed;
private double rudPosition = 0; // rudder position
private double boatSpeed = 4;
private double sailPosition = 0; // sheet position
public void setApparentWindSpeed() {
this.apparentWindSpeed = ApparentWindSpeed(getTrueWindSpeed(), getBoatSpeed(), trueWindAngle);
}
// W = true wind speed
// V = boat speed
// lambda = true pointing angle in degrees (0 = upwind, 180 = downwind)
//SOURCE: https://en.wikipedia.org/wiki/Apparent_wind
public double ApparentWindSpeed(double W, double V, double lambda){
return Math.sqrt(Math.pow(W,2) + Math.pow(V,2) + 2*W*V*Math.cos(lambda));
}
It works well when convert!
public class Direction extends Boat {
private double trueWindAngle = 60;
private double trueWindSpeed = 10;
private double apparentWindAngle;
private double apparentWindSpeed;
private double rudPosition = 0; // rudder position
private double boatSpeed = 4;
private double sailPosition = 0; // sheet position
// W = true wind speed
// V = boat speed
// lambda = true pointing angle in degrees (0 = upwind, 180 = downwind)
//SOURCE: https://en.wikipedia.org/wiki/Apparent_wind
public void setApparentWindSpeed() {
this.apparentWindSpeed = ApparentWindSpeed(getTrueWindSpeed(), getBoatSpeed(), Math.toRadians(trueWindAngle));
}
public double ApparentWindSpeed(double W, double V, double lambda){
return Math.sqrt(Math.pow(W,2) + Math.pow(V,2) + 2*W*V*Math.cos(lambda));
}
//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 am currently developing a "chaos game" for android. For those that don't know what it is: you pick some random numbers, and according to a given set of rules a dot is drawn somewhere on a canvas; after many iterations you get a shape, always the same.
In this case, it is a fern.
here is my code:
MainActivity.java
public class MainActivity extends Activity {
DrawView drawView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
drawView = new DrawView(this);
setContentView(drawView);
}
}
DrawView.java
public class DrawView extends View{
int viewWidth;
int viewHeight;
int iterations = 10000; // how many dots
int myColor;
Paint paint = new Paint();
Random rand = new Random();
public DrawView(Context context) {
super(context);
myColor = context.getResources().getColor(com.*****.******.*****.R.color.ferncolor); //Green
paint.setColor(myColor);
paint.setAntiAlias(true);
}
#Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld){
super.onSizeChanged(xNew, yNew, xOld, yOld);
viewWidth = xNew;
viewHeight = yNew;
}
#Override
public void onDraw(Canvas canvas) {
Double x = rand.nextDouble();
Double y = rand.nextDouble();
Double random;
for(int i = 0; i < iterations; i++){
random = rand.nextDouble();
if(random < 0.01){
x = 0.0;
y *= 0.16;
}
else if(random < 0.86){
x = (0.85 * x) + (0.04 * y);
y = (-0.04 * x) + (0.85 * y) + 1.6;
}
else if(random < 0.93){
x = (0.2 * x) - (0.26 * y);
y = (0.23 * x) + (0.22 * y) + 1.6;
}
else{
x = (-0.15 * x) + (0.28 * y);
y = (0.26 * x) + (0.24 * y) + 0.44;
}
Double posx = viewWidth/2.0 + x*viewWidth/7.5;
Double posy = y*viewHeight/10.2;
canvas.drawCircle(posx.floatValue(), posy.floatValue(), (float) 0.5, paint); //drawing dot at (posx,posy), size 0.5, with custom paint
}
}
}
My problem is that you have to wait for all the point to be drawn before you can see the view. That often leads to several awkward seconds blankness. What I would like is a "refresh" after every iteration (or every x iterations, depending on how much iterations I have).
I think that could be achieved via threading but I have no idea on how to achieve that.
Any ideas?
Thank you!
You can force a view to redraw by calling its invalidate() method. So you can try putting that at the end of your for loop.
More information here.
Also, invalidating too often could cause a performace slowdown, so if you want to draw 10000 dots, you could probably call invalidate only on every 500th iteration or something...