I am practicing some Java and one of the applications I am writing asks to output the world population in the next 75 years.
I am using the population growth model. My issue is that my application outputs 'Infinity' in the column where the estimated population should be output.
This is my code:
import java.util.Calendar;
import java.util.regex.Matcher;
public class WorldPopulationGrowth {
public static void main(String[] args) {
double currentWorldPopulation = 7.4e9;
double worldPopulationGrowthRate = 1.13;
double anticipatedWorldPopulation;
int initialYear = Calendar.getInstance().get(Calendar.YEAR);
System.out.println("Year\tAnticipated World Population (in billions)\tPopulation " +
"increase since last year");
System.out.println(String.format("%d\t%.1e\t\t\t\t\t\t\t\t\t\t\tNA", initialYear, currentWorldPopulation) );
for(int i=1; i < 76; i++){
int year = initialYear + i;
double growthExponential = worldPopulationGrowthRate*year*1.0;
anticipatedWorldPopulation = currentWorldPopulation * Math.pow(Math.E, growthExponential);
System.out.println(String.format("%d\t%.1e\t\t\t\t\t\t\t\t\t\t\t", year, anticipatedWorldPopulation));
currentWorldPopulation = anticipatedWorldPopulation;
}
}
}
Let's take a careful look at the first iteration of your code, as if we were debugging it (Make sure you try to do this in the future!)
currentWorldPopulation = 7.4e9
worldPopulationGrowthRate is 1.13
initialYear is 2016
your loop begins, i is 1
year is set to 2017
growthExponential is set to 1.13 * 2017 = 2279.21 (this is the start of your problem)
anticipatedWorldPopulation is set to 7.4e9 * e^2279.21
this is roughly 7.4e9 * 7.05e989... KABOOM
Revisit your calculations, and step through your application (ideally in a debugger) to see your problems.
#Krease found your problem.
I recoded it. Once you fix the issue he found it's fine. I used JDK 8 lambdas and gave you both percentage and exponential growth models. The code prints both for comparison:
import java.util.function.DoubleFunction;
/**
* Simplistic population growth model
* #link https://stackoverflow.com/questions/38805318/getting-infinity-output-instead-of-actual-numbers/38805409?noredirect=1#comment64979614_38805409
*/
public class WorldPopulationGrowth {
public static void main(String[] args) {
double currentWorldPopulation = 7.4e9;
double worldPopulationGrowthRate = 1.13;
int numYears = 76;
int startYear = 1976;
double populationExponential = currentWorldPopulation;
ExponentialGrowthModel modelExpGrowth = new ExponentialGrowthModel(worldPopulationGrowthRate);
double populationPercentage = currentWorldPopulation;
PercentageGrowthModel modelPercentGrowth = new PercentageGrowthModel(worldPopulationGrowthRate);
System.out.println(String.format("%10s %20.3e %20.3e", startYear, currentWorldPopulation, currentWorldPopulation));
for (int i = 1; i < numYears; ++i) {
populationExponential = modelExpGrowth.apply(populationExponential);
populationPercentage = modelPercentGrowth.apply(populationPercentage);
System.out.println(String.format("%10s %20.3e %20.3e", startYear+i, populationExponential, populationPercentage));
}
}
}
class ExponentialGrowthModel implements DoubleFunction<Double> {
private double exponent;
ExponentialGrowthModel(double exponent) {
this.exponent = exponent;
}
private double getExponent() {
return exponent;
}
public void setExponent(double exponent) {
this.exponent = exponent;
}
#Override
public Double apply(double value) {
return value*Math.exp(this.getExponent());
}
}
class PercentageGrowthModel implements DoubleFunction<Double> {
private double percentageIncrease;
PercentageGrowthModel(double percentageIncrease) {
this.percentageIncrease = percentageIncrease;
}
private double getPercentageIncrease() {
return percentageIncrease;
}
public void setPercentageIncrease(double percentageIncrease) {
this.percentageIncrease = percentageIncrease;
}
#Override
public Double apply(double value) {
return value*(this.getPercentageIncrease());
}
}
Related
I have the following code modeling a lightweight framework for a vertex in my study of network diffusion. The initial prototype was from a framework in python, which I translated into Java. The issue I have is that while this code runs much faster than its python version up to 10000 vertices, for a larger number of vertices (100,000+), it grinds to a halt. In fact the python version executed in 1.2 minutes, while the java build didn't return even after 7 minutes of execution. I am not sure why the same code is breaking down at a larger number of vertices and I need help on fixing the code.
import java.util.*;
public class Vertex
{
private int id;
private HashMap<Integer, Double> connectedTo;
private int status;
public Vertex(int key)
{
this.id = key;
this.connectedTo = new HashMap<Integer, Double>();
this.status = 0;
}
public void addNeighbour(int nbr, double weight)
{
this.connectedTo.put(nbr, weight);
}
public int getId()
{
return this.id;
}
public double getWeight(int nbr)
{
return this.connectedTo.get(nbr);
}
public int getStatus()
{
return this.status;
}
public Set<Integer> getConnections()
{
return this.connectedTo.keySet();
}
//testing the class
public static void main(String[] args)
{
int noOfVertices = 100000;
Vertex[] vertexList = new Vertex[noOfVertices];
for (int i = 0; i < noOfVertices; i++) {
vertexList[i] = new Vertex(i);
}
for (Vertex v : vertexList) {
int degree = (int)(500*Math.random()); //random choice of degree
int neighbourCount = 0; // count number of neighbours built up
while (neighbourCount <= degree) {
int nbr = (int) (noOfVertices * Math.random()); // randomly choose a neighbour
double weight = Math.random(); // randomly assign a weight for the relationship
v.addNeighbour(nbr, weight);
neighbourCount++;
}
}
}
}
For reference, the python version of this code is as follows:
import random
class Vertex:
def __init__(self, key):
self.id = key
self.connectedTo = {}
def addNeighbor(self, nbr, weight=0):
self.connectedTo[nbr] = weight
def __str__(self):
return str(self.id) + ' connectedTo: ' \
+ str([x.id for x in self.connectedTo])
def getConnections(self):
return self.connectedTo.keys()
def getId(self):
return self.id
def getWeight(self, nbr):
return self.connectedTo[nbr]
if __name__ == '__main__':
numberOfVertices = 100000
vertexList = [Vertex(i) for i in range(numberOfVertices)] # list of vertices
for vertex in vertexList:
degree = 500*random.random()
# build up neighbors one by one
neighbourCount = 0
while neighbourCount <= degree:
neighbour = random.choice(range(numberOfVertices))
weight = random.random() # random choice of weight
vertex.addNeighbor(neighbour, weight)
neighbourCount = neighbourCount + 1
This was a very interesting problem, and I believe I learned something new as well. I tried optimizing the code in different ways, such as utilizing a parallel stream as well as using ThreadLocalRandom which can be up to three times faster than Random. However, I finally discovered the main bottleneck: allocated memory to the JVM.
Because you have so many elements being added to your Map (worst case is 500,000 with 100,000 vertices), you'll require a lot of memory (heap space). If you allow the JVM to dynamically allocate memory, then the program will take a very long time to execute. The way that I solved this was to pre-allocate memory to the JVM (specifically 3 GB) by applying -Xms3G as a VM Argument to the program's Run Configuration which can be done in your IDE or via the terminal.
I've also optimized your code a bit which I will post below (it completes in just a few seconds for me):
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.*;
public class Test {
private static final ThreadLocalRandom RANDOM = ThreadLocalRandom.current();
public static void main(String[] args) {
int noOfVertices = 100_000;
Vertex[] vertexList = new Vertex[noOfVertices];
IntStream.range(0, noOfVertices).parallel().forEachOrdered(i -> {
vertexList[i] = new Vertex(i);
int degree = (int) (500 * RANDOM.nextDouble()); // random choice of degree
for (int j = 0; j <= degree; j++) {
int nbr = (int) (noOfVertices * RANDOM.nextDouble()); // randomly choose a neighbor
vertexList[i].addNeighbour(nbr, RANDOM.nextDouble());
}
});
}
}
class Vertex {
private int id;
private Map<Integer, Double> connectedTo;
private int status;
public Vertex(int id) {
this.id = id;
this.connectedTo = new HashMap<>(500);
}
public void addNeighbour(int nbr, double weight) {
this.connectedTo.put(nbr, weight);
}
public int getId() {
return this.id;
}
public double getWeight(int nbr) {
return this.connectedTo.get(nbr);
}
public int getStatus() {
return this.status;
}
public Set<Integer> getConnections() {
return this.connectedTo.keySet();
}
}
I'm not sure of the explicit consequences regarding using ThreadLocalRandom in a multithreaded environment, but you can switch it back to Math#random if you'd like.
So i am trying to build a genetic algorithm on java i stuck on getting
fitness of my population here 3 classes from my project:
Class Individu
public class Individu {
int Popsize=4;
int Health[]= new int[Popsize];
int Attack[]= new int[Popsize];
int Atspeed[]= new int[Popsize];
int Move[]= new int[Popsize];
int health,attack,lifetime,dmgdone,attspeed,range,move;
double fitness;
double Pitness[]= new double[20];
Random random = new Random();
public int setHealth(){
health = random.nextInt(150 - 75) + 75;
return health;
}
public int setAttack(){
attack = random.nextInt(10 - 5) + 10;
return attack;
}
public int setAttspeed(){
attspeed = random.nextInt(3 - 1) + 3;
return attspeed;
}
public int setMoveSpeed(){
move = random.nextInt(8 - 4) + 1;
return move;
}
public int getGeneHealth(int index) {
return Health[index];
}
public int getGeneAttack(int index) {
return Attack[index];
}
public int getGeneAtspedd(int index) {
return Atspeed[index];
}
public int getGeneMove(int index) {
return Move[index];
}
public void setGene(int index, int value) {
Health[index]=value;
Attack[index]=value;
Atspeed[index]=value;
Move[index]=value;
fitness = 0;
}
public int size() {
return Popsize;
}
public double[] GenerateIndividual(){
for (int i = 0; i <Popsize; i++) {
Health[i]=setHealth();
Attack[i]=setAttack();
Atspeed[i]=setAttspeed();
Move[i]=setMoveSpeed();
}
return Pitness;
}
Class Fitness
public class Fitness {
Individu individu= new Individu();
double fitness;
double Pitness[]= new double[20];
public double getFitness(){
individu.GenerateIndividual();
for (int i = 0; i <=3; i++) {
fitness=
individu.getGeneHealth(i)+individu.getGeneAtspedd(i)+
individu.getGeneAttack(i)+
individu.getGeneMove(i));
fitness=fitness/171;
Pitness[i]=fitness;
System.out.println("Health from class
fitness"+individu.Health[i]);
}
return fitness;
}
}
Main Class
public class main {
public static void main(String[] args) {
Individu aaa=new Individu();
Fitness bbb= new Fitness();
bbb.getFitness();
aaa.GenerateIndividual();
DecimalFormat df = new DecimalFormat();
df.setMaximumFractionDigits(3);
for (int i=0; i<=3; i++){
//System.out.println("Fitness ");
System.out.println("Generasi ke :"+i+1);
System.out.println("Health "+aaa.getGeneHealth(i));
System.out.println("Attackspeed "+aaa.getGeneAtspedd(i));
System.out.println("Attack "+aaa.getGeneAttack(i));
System.out.println("movementSpeed "+aaa.getGeneMove(i));
}
}
}
What i struggle is when i run this script i got 2 double value from 1 variable first value is from Fitness class as i printed here
System.out.println("Health from class fitness"+individu.Health[i]);
and second variable i printed here from Main Class
System.out.println("Health "+aaa.getGeneHealth(i));
that 2 variable is always have different value causing my fitness and my generation is not correlated each other.
My question is how to make this 2 variable print same value?
Well, aside from the many problems I can detect about the essentials of Genetic Algorithms, I see 'individu' and 'aaa' are two different Java objects.
Individu aaa=new Individu();
aaa.GenerateIndividual();
and
Individu individu= new Individu();
individu.GenerateIndividual();
Since your Health and Fitness are randomly generated on GenerateIndividual(), both 'aaa' and 'individu' will get different Health values.
I strongly recommend you to review GA essentials, since I can see many conception errors in your system.
The JUnit test keeps failing my addScore method, however I know for sure that the scores were added, which means that most likely my toString maybe wrong. However I cannot figure out what is wrong with it. Please Help.
import java.util.ArrayList;
public class GradeBook
{
private double[] scores;
private int scoresSize;
/**
Constructs a gradebook with no scores and a given capacity.
#capacity the maximum number of scores in this gradebook
*/
public GradeBook(int capacity)
{
scores = new double[capacity];
scoresSize = 0;
}
/**
Adds a score to this gradebook.
#param score the score to add
#return true if the score was added, false if the gradebook is full
*/
public boolean addScore(double score)
{
if (scoresSize < scores.length)
{
scores[scoresSize] = score;
scoresSize++;
return true;
}
else
return false;
}
/**
Computes the sum of the scores in this gradebook.
#return the sum of the scores
*/
public double sum()
{
double total = 0;
for (int i = 0; i < scoresSize; i++)
{
total = total + scores[i];
}
return total;
}
/**
Gets the minimum score in this gradebook.
#return the minimum score, or 0 if there are no scores.
*/
public double minimum()
{
if (scoresSize == 0) return 0;
double smallest = scores[0];
for (int i = 1; i < scoresSize; i++)
{
if (scores[i] < smallest)
{
smallest = scores[i];
}
}
return smallest;
}
/**
Gets the final score for this gradebook.
#return the sum of the scores, with the lowest score dropped if
there are at least two scores, or 0 if there are no scores.
*/
public double finalScore()
{
if (scoresSize == 0)
return 0;
else if (scoresSize == 1)
return scores[0];
else
return sum() - minimum();
}
/**
* Gets the score size from the GradeBook
* #param scoresSize The score size
* #return scoresSize The score size
*/
public int getScoreSize(int scoresSize){
return scoresSize;
}
public String toString(){
String out = null;
for(int i = 0; i < 5; i++){
out += (Double.toString(scores[i]) + " ");
}
return out;
}
}
That is the main class and now the JUnit test;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class GradeBookTest {
GradeBook g1;
GradeBook g2;
GradeBook g3;
#Before
public void setUp() throws Exception {
g1 = new GradeBook(5);
g1.addScore(50);
g1.addScore(43);
g1.addScore(22);
g1.addScore(4);
g1.addScore(100);
g2 = new GradeBook(5);
g2.addScore(43);
g2.addScore(34);
g2.addScore(67);
g2.addScore(82);
g2.addScore(97);
g3 = new GradeBook(5);
g3.addScore(13);
g3.addScore(25);
g3.addScore(90);
g3.addScore(78);
g3.addScore(100);
}
#After
public void tearDown() throws Exception {
g1 = null;
g2 = null;
g3 = null;
}
#Test
public void testAddScore() {
assertTrue(g1.toString().equals("50.0 43.0 22.0 4.0 100.0 "));
assertTrue(g2.toString().equals("43.0 34.0 67.0 82.0 97.0 "));
assertTrue(g3.toString().equals("13.0 25.0 90.0 78.0 100.0 "));
}
#Test
public void testSum() {
assertEquals(219, g1.sum(), .0001);
assertEquals(323, g2.sum(), .0001);
assertEquals(306, g3.sum(), .0001);
}
#Test
public void testMinimum() {
assertEquals(4, g1.minimum(), .001);
assertEquals(34, g2.minimum(), .001);
assertEquals(13, g3.minimum(), .001);
}
#Test
public void testFinalScore() {
assertEquals(215, g1.finalScore(), .0001);
assertEquals(289, g2.finalScore(), .0001);
assertEquals(293, g3.finalScore(), .0001);
}
}
Found where the problem was.
I had initialized my string variable in the toString() assignment to null and added to that value.
Once I changed that, my program worked.
The problem is Double.toString(100) does not necessarily result in 100. Converting double values to strings in Java will usually include a decimal point and some digits after.
Here is an example program to prove the point:
public class DoubleTest {
public static void main(String[] args) {
System.out.println(Double.toString(100));
}
}
Because of this, you have several options:
change your toString method to output double values with a known format (using java.text.NumberFormat for instance), or
change your testAddScore test to construct a different expected strings
avoid using toString all together for assertions and assert the values in the collection instead.
I have an assignment to write a program to project your annual fuel usage based on three fill ups of a car. I have to use two separate classes. This is my first class, titled AnnualFuelUse.
public class AnnualFuelUse
{
private static int endMiles, startMiles,fillUp, days,distance;
private double gallonsUsed, pricePerGallon,MPG,cost;
AnnualFuelUse(int fu, int d, int sm, int em, double gu, double price)
{
fillUp = 0;
days = d;
startMiles = sm;
endMiles = em;
gallonsUsed = gu;
pricePerGallon = price;
distance = 0;
MPG = 0.0;
cost = 0.0;
}
public void calcDistance ()
{
distance = endMiles - startMiles;
}
public int getDistance(){
return distance;
}
//calculates miles per gallon
public void calcMPG()
{
MPG = distance /gallonsUsed;
}
public double returnMPG(){
return MPG;
}
public void totalCost(){
cost= gallonsUsed * pricePerGallon;
}
public double getCost(){
return cost;
}
public int returnStart(){
return startMiles;
}
public int returnEnd(){
return endMiles;
}
public int returnDays(){
return days;
}
public double returnGallons(){
return gallonsUsed;
}
public double returnPrice(){
return pricePerGallon;
}
}
This is my second class, titled AnnualFuelUseTester. (sorry for the long names, but it's required)
public class AnnualFuelUseTester
{
public static void main(String[]args)
{
AnnualFuelUse[]fuel = {new AnnualFuelUse(1,1,45023,45231,10.00,2.95),
new AnnualFuelUse(2,4,45231,45480,11.70,2.99),
new AnnualFuelUse(3,8,45480,45659,9.30,3.01),
new AnnualFuelUse(4,13,45659,45961,14.90,3.01)};
for (int index = 0; index<fuel.length;index++)
{
fuel[index].calcDistance();
fuel[index].calcMPG();
fuel[index].totalCost();
}
System.out.println(" Fill Up Days Start Miles End Miles Distance Gallons Used MPG Price Cost ");;
for(int index = 0; index < fuel.length; index++)
{
System.out.printf("%5d %6d %9d %12d %12d %10.2f %13.1f %6.2f %6.2f \n",
index+1,fuel[index].returnDays(),fuel[index].returnStart(),fuel[index].returnEnd(),fuel[index].getDistance(),fuel[index].returnGallons(),fuel[index].returnMPG(),fuel[index].returnPrice(),fuel[index].getCost());
}
My problem is that when I run the program, the days, start miles, end miles, and distance columns all have the same numbers in them, the data for the last fill up. The gallons used, MPG, Price, Cost, all work fine. So in the Days Column, instead of reading 1, 4, 8, 13, it reads 13, 13, 13, 13.
I would appreciate some help in fixing this problem.
Your fields should not be static. That means one per class (not instance)
private static int endMiles, startMiles,fillUp, days,distance;
should be
private int endMiles, startMiles,fillUp, days,distance;
Can anyone see what is wrong with my code? I get 0 from return of the calculation.
Created a small calculation on second class and pass the result data to main class, then print.
main class
package javaapplication3;
public class JavaApplication3 {
public static void main(String[] args) {
cal bla = new cal();
bla.getRatio();
String dCount = String.valueOf(bla.getRatio());
System.out.print(dCount);
}
}
second class
package javaapplication3;
public class cal {
public int total = 11;
public int count = 2508;
public int calRatio;
public void caln () {
calRatio = count / total;
System.out.print(calRatio);
}
public int getRatio () {
return (calRatio);
}
}
PS: By changing bla.getRatio to bla.caln(); worked. I think I've got other projects mixed up. Thanks for the input guys.
You're doing integer division, which truncates the result to an integer.
You need to cast either operand to double.
bla.getRatio();
String dCount = String.valueOf(bla.getRatio());
You never call the caln()-method, so calRatio is 0 forever.
Maybe you meant the following:
bla.caln();
String dCount = String.valueOf(bla.getRatio());
Plus, you try to divide integers. Try this:
public class cal {
public int total = 11;
public int count = 2508;
public double calRatio;
public void caln () {
calRatio = count / total;
System.out.print(calRatio);
}
public double getRatio () {
return calRatio;
}
}
You never call the "setter" function caln(), so calRatio was never set. So it returns the 0 for calRatio.
replace
public void caln () {
calRatio = count / total;
System.out.print(calRatio);
}
by this
public cal () {
calRatio = count / total;
System.out.print(calRatio);
}
Try this:
public static void main(String[] args) {
cal bla = new cal();
bla.caln();
String dCount = String.valueOf(bla.getRatio());
System.out.print(dCount);
}
I get 0 from return of the calculation.
As you should. 11 / 2508 does an integer division which is 0
If you want a non-zero I suggest changing
public double getAverage () {
return (double) total / count;
}
Normally you divide the total by the count to get the average.
It will return 0, always, because you are returning an int type. The result of your division will always be some floating point value, so you need to store it as such, and return it.
public class cal {
public int total = 11;
public int count = 2508;
public double calRatio;
public void caln() {
calRatio = (double)count / (double)total;
System.out.print(calRatio);
}
}