Using info from two arrays to calculate contents of third array - java

I have an array with the total population of a country and another array with the total number of cases of COVID for each country. I need to divide the number of cases by the total population and store the percentage in a third array. I'm stuck on the syntax though and no one from my class is available for outreach until tomorrow. Can anyone please help me get past this step? I've tried lots of different ways of getting the new percentage array, but nothing works. I can't use int for the percentage because my professor wants it with four places after the decimal. No references in the examples or the book match what I'm trying to do.
Thanks in advance for your advice!
int[] cases = {10_036_282, 8_553_657, 5_675_032, 1_856_292, 1_781_997, 1_381_218, 1_250_499, 1_216_747, 1_149_068, 967_825};
int[] population = {327_096_265, 1_352_647_786, 209_469_323, 64_990_511, 145_734_038, 46_692_858, 44_361_150, 67_141_684, 49_661_048, 126_190_788};
//You must calculate the percentage of cases based on the number of cases and the population.
for (int i = 0; i < countries.length; i++){
double percentage[i] = ((cases[i] / population[i]) * 100);
}

Unless otherwise explicitly instructed, you should use doubles for percentages. Otherwise, cases[i] / population[i] is going to normally result in 0
double[] percentage = new double[...];
percentage[i] = ((cases[i] / (double)population[i]) * 100);

For simplification calculate everything just put into double and than convert the calculated value to int and store in the array.
Here you go!
import java.util.Queue;
import java.util.LinkedList;
import java.util.Arrays;
class Main{
public static void main (String[] args) {
int[] cases = {10_036_282, 8_553_657, 5_675_032};
int[] population = {327_096_265, 1_352_647_786, 209_469_323};
int[] percentage = new int[cases.length];
for(int i = 0; i < cases.length; i++){
double temp = ((double)cases[i] / (double)population[i] ) * 100;
int pr = (int) temp;
percentage[i] = pr;
}
System.out.println(Arrays.toString(percentage));
}
}

all of your number is in integer and division of integer by integer is an integer, at first you need to cast one or all of the values to double, and secondly you said with 4 decimal points so you need to format your decimal number as below:
int[] cases = { 10_036_282, 8_553_657, 5_675_032, 1_856_292, 1_781_997, 1_381_218, 1_250_499, 1_216_747,
1_149_068, 967_825 };
int[] population = { 327_096_265, 1_352_647_786, 209_469_323, 64_990_511, 145_734_038, 46_692_858, 44_361_150,
67_141_684, 49_661_048, 126_190_788 };
double[] average = new double[cases.length];
for (int i = 0; i < average.length; i++) {
average[i] = ((cases[i] / (double)population[i]) * 100.0);
average[i] = Double.parseDouble(String.format("%.4f", average[i]));
}

Related

Weighted-random probability in Java

I have a list of fitness values (percentages), which are ordered in descending order:
List<Double> fitnesses = new ArrayList<Double>();
I would like to choose one of these Doubles, with an extreme likelyhood of it being the first one, then decreasing likelyhood for each item, until the final one is close to 0% chance of it being the final item in the list.
How do I go about achieving this?
Thanks for any advice.
If you want to select "one of these Doubles, with an extreme likelihood of it being the first one, then decreasing likelihood for each item, until the final one is close to 0% chance of it being the final item in the list" then it seems like you want an exponential probability function. (p = x2).
However, you will only know whether you have chosen the right function once you have coded a solution and tried it, and if it does not suit your needs then you will need to choose some other probability function, like a sinusoidal (p = sin( x * PI/2 )) or an inverse ratio (p = 1/x).
So, the important thing is to code an algorithm for selecting an item based on a probability function, so that you can then try any probability function you like.
So, here is one way to do it.
Note the following:
I am seeding the random number generator with 10 in order to always produce the same results. Remove the seeding to get different results at each run.
I am using a list of Integer for your "percentages" in order to avoid confusion. Feel free to replace with a list of Double once you have understood how things work.
I am providing a few sample probability functions. Try them to see what distributions they yield.
Have fun!
import java.util.*;
public final class Scratch3
{
private Scratch3()
{
}
interface ProbabilityFunction<T>
{
double getProbability( double x );
}
private static double exponential2( double x )
{
assert x >= 0.0 && x <= 1.0;
return StrictMath.pow( x, 2 );
}
private static double exponential3( double x )
{
assert x >= 0.0 && x <= 1.0;
return StrictMath.pow( x, 3 );
}
private static double inverse( double x )
{
assert x >= 0.0 && x <= 1.0;
return 1/x;
}
private static double identity( double x )
{
assert x >= 0.0 && x <= 1.0;
return x;
}
#SuppressWarnings( { "UnsecureRandomNumberGeneration", "ConstantNamingConvention" } )
private static final Random randomNumberGenerator = new Random( 10 );
private static <T> T select( List<T> values, ProbabilityFunction<T> probabilityFunction )
{
double x = randomNumberGenerator.nextDouble();
double p = probabilityFunction.getProbability( x );
int i = (int)( p * values.size() );
return values.get( i );
}
public static void main( String[] args )
{
List<Integer> values = Arrays.asList( 10, 11, 12, 13, 14, 15 );
Map<Integer,Integer> counts = new HashMap<>();
for( int i = 0; i < 10000; i++ )
{
int value = select( values, Scratch3::exponential3 );
counts.merge( value, 1, ( a, b ) -> a + b );
}
for( int value : values )
System.out.println( value + ": " + counts.get( value ) );
}
}
Here's another way of doing it that gives you the ability to approximate an arbitrary weight distribution.
The array passed to WeightedIndexPicker indicates the number of "buckets" (>0) that should be allocated to each index. In your case these would be descending, but they don't have to be. When you need an index, pick a random number between 0 and the total number of buckets and return the index associated with that bucket.
I've used an int weight array as it's easier to visualize and it avoids rounding errors associated with floating point.
import java.util.Random;
public class WeightedIndexPicker
{
private int total;
private int[] counts;
private Random rand;
public WeightedIndexPicker(int[] weights)
{
rand = new Random();
counts = weights.clone();
for(int i=1; i<counts.length; i++)
{
counts[i] += counts[i-1];
}
total = counts[counts.length-1];
}
public int nextIndex()
{
int idx = 0;
int pick = rand.nextInt(total);
while(pick >= counts[idx]) idx++;
return idx;
}
public static void main(String[] args)
{
int[] dist = {1000, 100, 10, 1};
WeightedIndexPicker wip = new WeightedIndexPicker(dist);
int idx = wip.nextIndex();
System.out.println(idx);
}
}
I don't think you need all this code to answer your question since your question seems to be much more about math than code. For example, using the apache commons maths library getting a distribution is easy:
ExponentialDistribution dist = new ExponentialDistribution(1);
// getting a sample (aka index into the list) is easy
dist.sample();
// lot's of extra code to display the distribution.
int NUM_BUCKETS = 100;
int NUM_SAMPLES = 1000000;
DoubleStream.of(dist.sample(NUM_SAMPLES))
.map(s->((long)s*NUM_BUCKETS)/NUM_BUCKETS)
.boxed()
.collect(groupingBy(identity(), TreeMap::new, counting()))
.forEach((k,v)->System.out.println(k.longValue() + " -> " + v));
However, as you said, there are so many possible distributions in the math library. If you are writing code for a specific purpose then the end user will probably want you to explain why you chose a specific distribution and why you set the parameters for that distribution the way you did. That's a math question and should be asked in the mathematics forum.

Statistical method

So in my code, it seems that in the fillRandomArray method, instead of getting an array of 100 random numbers, I just get straight zeros and I don't know how to fix it. It seems to me that the problem has to do with the first for loop, or potentially the declaration of the double array in the public class statistical model.
import javax.swing.*;
import java.util.*;
import java.util.Arrays;
public class statisticalModel {
//Initates a place for the normal curve to be placed.
static double Ho;
//Real proportion of data statistic.
static double Ha;
//Estimated real proportion of data statistic.
static int Pop;
//Population size.
static int Zscore;
//Z score, or the amount of standard deviations away from the mean.
//Z score = sqrt(P(1-p)/N)
static double stdDev;
//Standard Deviation, follows the 65, 95, 99 model. 65 percent of all scores
//fall in one standard deviation of the mean. 95 percent of all scores fall
//within two standard deviations of the mean. 99 percent of all scores fall
//within three standard deviations of the mean.
static double mean;
//The average of all the scores of the array.
static double variance;
//The average difference between sets of values within the array.
static double[] meanScores = new double[100];
//Array meant to generate a set of random values within the normal curve of
//the model, following the 65, 95, 99 rule.
static String desiredValue = "";
//This is a string set to the user's command. Tells whether or not the value should
//be lower than, higher than, or not equal to Ho.
static Scanner sc = new Scanner(System.in);
//Scanner to take in values listed above.
static int size = 100;
//Variable that measures the size of the array.
static int temporary;
//Value Holder for For Loops, While Loops, If Statements, etc.
static double pValue;
//P Value which represents how far a statistic deviates from the expected mean of a population.
public static void main(String args[])
{
runStatisticalMethod();
}
public static void runStatisticalMethod()
{
takeInData();
calculateStats();
System.out.println(Arrays.toString(meanScores));
explainSolution();
}
public static void takeInData()
{
System.out.println("Please enter your desired Ho");
Ho = sc.nextDouble();
System.out.println("Please enter your desired Ha");
Ha = sc.nextDouble();
System.out.println("Please enter your desired population size");
Pop = sc.nextInt();
System.out.println("Thanks for entering your data. Your data will be compiled below");
}
//Fills the array meanScores with random integers.
public static void fillRandomArray()
{
for (int z = 0; z < 100; z++) {
meanScores[z] = (Math.random() * 100) + (stdDev * 3);
}
assignStdDev();
for (int x = 0; x < 99; x++) {
for (int y = 0; y < 99; y++) {
if (meanScores[y] >= meanScores[y + 1]) {
double valueHolder1 = meanScores[y];
double valueHolder2 = meanScores[y + 1];
meanScores[y + 1] = valueHolder1;
meanScores[y] = valueHolder2;
}
}
}
}
public static void assignStdDev()
{
for (int x = 5; x >= 5 && x <= 95; x++) {
meanScores[x] -= (stdDev * Math.random());
}
for (int x = 31; x >= 31 && x < 66; x++) {
meanScores[x] -= (stdDev * Math.random());
}
}
//Calculates a set of statistics including standard deviation, z-score, mean,
//interquartile range, probability, and variance.
public static void calculateStats()
{
//Calculates the Mean of the inputted variables and normal curve.
int sum = 0;
for (int a = 0; a < 100; a++) {
sum += a;
}
mean = sum / size;
//Calculate the Variance of the inputted variables and normal curve.
for (int b = 0; b < 100; b++) {
temporary += (b - mean) * (b - mean);
}
variance = temporary / size;
//Calculate the Standard Deviation of the inputted variables and normal curve.
stdDev = Math.sqrt(variance);
//Calculate the P-Value and use the p value to determine whether or not the hypothesis is valid.
pValue = (Ha - Ho) / (stdDev / Math.sqrt(Pop));
}
//This method explains the numbers generated in terms of statistics and analyzes
//if the hypothesis is probably. If not, a possible solution is proposed with
//regards to what should be changed. Also explains the curve of the graph.
public static void explainSolution()
{
if (Math.abs(pValue) < .05) {
System.out.println(
"Based on the information you have given me, the hypothesis test seems to show information that your Ha is possibly correct, thus failing to reject your hypothesis");
} else if (Math.abs(pValue) > .05) {
System.out.println(
"Based on the information you have given me, the hypothesis test seems to lack information to show that your Ha is possibly correct, thus rejecting your hypothesis");
}
}
}

BigInteger Wrong Answer

I was calculating a simple combination using java, when I define the result as double, the answer seems right, only lost some precision, but when I use the BigInteger class, the answer looks just wrong at all, I don't see why it's like that, here is the code.
import java.math.BigInteger;
import java.util.Scanner;
public class Test {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
System.out.println("Please input the lottery sum");
int num = in.nextInt();
System.out.println("Please input the available sum");
int avail = in.nextInt();
//double sum = 1;
BigInteger sum = BigInteger.ONE;
for (int i = avail - 1; i >= 1;i--){
//sum = sum*(num - i) / i;
sum = sum.multiply(BigInteger.valueOf(num - i)).divide(BigInteger.valueOf(i));
}
//sum = sum * num / avail;
sum = sum.multiply(BigInteger.valueOf(num)).divide(BigInteger.valueOf(avail));
System.out.println(sum);
in.close();
}
}
The main difference between double and BigInteger is that one is using float-point maths, and other is using integer maths. This means that, when you using BigInteger, the result of every division gets truncated.
I'm not sure what you're calculating, but I suspect that the integer division is what's causing the observed differences.
I suppose that you get the same result with BigInteger and a regular int for small examples.
For example:
double:
3.0/2.0 = 1.5
(Big)Integer:
3/2 = 1
If you sum over such divisions multiple times, the discrepancy gets bigger and bigger.
Take a look at BigDecimal, that may be the solution you're after to avoid this error introduced by integer divisions.

Converting from int to double in java

the following code calculates change dispensed by a vending machine. My problem? I cant get the change variable to work as the compiler wont let me due to two different data types (int & double conversion). Can anyone please help me solve this problem.
I have tried casting "change" but then it wont print right amount.
For example, if the change is 0.25 cents, change value remains zero..for obvious reasons of course. The problem begins at line 16. I have commented the part giving example as change = 0.25.
public String[] itemList = new String[] {"Water ","Coke ", "Diet Coke", "Iced Tea","Fanta "};
public double[] priceList = new double[] {75,120, 120, 100, 150};
public int[] itemQty = new int[]{10,10,10,10,10};
public int[] coinList = new int[]{100,50,20,10,5};
public int[] coinQty = new int[]{10,10,10,10,10};
public double change;
public double paid;
public void ReturnChange()
{
int Denominations=5;
int coins_dispensed = 0 ;
int[] InitialArray = new int[Denominations];
//My Problem begins here..for example if change is computed
change = 0.25; //change is a global declaration of type double and carries values derived from different function
int change1 = (int)change; //if i cast here, i get change as 0, thus the part that follows, fails to compute coins dispensed.
for (int i=0; i < 5; i++)
{
InitialArray[i] += coinQty[i]; // Copies Coin Quantity to Initial array for difference
}
System.out.println("Your change is "+NumberFormat.getCurrencyInstance().format(Math.abs(change1)) +" which comprises of:"); //OK till here
for (int i=0; i<5; i++)
{
if (coinQty[i]>0) //if a particular denomination is available
{
coins_dispensed = (change1/coinList[i]); //dividing coins dispense with denomination
coinQty[i] -= coins_dispensed; //reduce the quantity of the denomination dispensed
change1 = change1 - (coinList[i] * coins_dispensed); //total the change
}
else // Moves to next denomination if a particular coin runs out
{
coins_dispensed = (change1/coinList[i+1]);
coinQty[i+1] -= coins_dispensed ;
change1 = change1 - (coinList[i+1] * coins_dispensed);
}
}
if (change1 != 0) // In the case not enough coins to make change, selection is ignored.
{
System.out.println("\n\n\t Sorry. The machine doesnt have enough coins to make up your change. Your last transaction has been ignored.");
}
else
{
for (int i=0; i<Denominations; i++)
{
coins_dispensed = InitialArray[i] - coinQty[i];
System.out.println( "\n\t\t\t" + coins_dispensed +" of "+ coinList[i] + " cents coins");
}
}
}
You should use use integers everywhere but count in cents not dollars. Just divide your numbers by 100 when you print them.
This is because floats and doubles cannot accurately represent the base 10 multiples used for money and will introduce rounding errors, particularly when multiplying to calculate interest rates for example.
See Why not use Double or Float to represent currency? for more information and discussion.
It seems all your variables hold prices in cents (i guess a coke is not 120 $). But your change is apparently specified in dollars. So what you could do is multiply change by 100 and then cast it to int.
Like that:
int change1 = (int) (change * 100); // convert dollars to cents and cast to int
If you need to output change1 in dollars (and not cents) at some point, you have to convert it back:
float result = change1 / 100.0f;

Program gives same result every time when it should be random

The goal of this program is to take 2 random variables for a fraction and see if they are already in reduced terms or not. The supposed probability of this is 6/(pi^2). I run 1,000 different combinations of variables and determine how many were and were not already reduced. Then I solve for pi.
But the output is giving me "pi is 2.449489742783178" every time I run it.
Anyone know why? Thanks.
import java.util.*;
public class ratio1 {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int nonReducedCount = 0; //counts how many non reduced ratios there are
for(int i =1; i<=1000; i++){
Random rand = new Random();
int n = rand.nextInt(1000)+1; //random int creation
int m = rand.nextInt(1000)+1;
//Ratio ratio = new Ratio(n,m);
if (gcd(n,m)> 1 ){ // if the ratio was not already fully reduced
nonReducedCount++; // increase the count of non reduced ratios
}
}
int reducedCount = 1000 - nonReducedCount; //number of times the ratio was reduced already
double reducedRatio = reducedCount / nonReducedCount; //the ratio for reduced and not reduced
reducedRatio *= 6;
reducedRatio = Math.sqrt(reducedRatio);
System.out.println("pi is " + reducedRatio);
}
public static int gcd(int a, int b) { return b==0 ? a : gcd(b,a%b); }
}
When you divide two integers, you get integer division, with an integer result, even if you later assign the result to a double. Try
double reducedRatio = (double)reducedCount / nonReducedCount;
i.e. convert one of the operands to a double.

Categories

Resources