Computing Variance/Standard deviation - JAVA - java

There is a table with purchase details. Let say, an item "chocolate" is sold 1500 in total for past one week (one week from yesterday). Yesterday it was sold 230 in total. I have counts for per day and per week.
is it possible to get variance/standard deviation by taking an average on count past week and compare with yesterday count. basically variance / sd on avg(1500) and 230. Please suggest if its correct way to and advice on how to do it in java.
Thanks in advance.

Please take a look at this answer:
https://stackoverflow.com/a/36186227/8310211
Maybe you want to modify it to use a double[] array as input:
public static double stdDev(double[] inputArray) {
double sum = 0;
double sq_sum = 0;
for (int i = 0; i < inputArray.length; ++i) {
double ai = inputArray[i];
sum += ai;
sq_sum += ai * ai;
}
double mean = sum / inputArray.length;
double variance = sq_sum / inputArray.length - mean * mean;
return Math.sqrt(variance);
}

Related

For loop in Java not working how I expected. Can someone help me out?

I have a loop in Java that is meant to calculate values for an array and put them in each index.
Here is what I have:
for(int i = 15; i <= 30; i += 5){
double rate = 0.03;
int index = 0;
payments[index] = LoanCalculator(initLoan, rate, i*12);
index++;
}
System.out.println();
System.out.printf("%-2.1f%c", 3.0, percent);
System.out.printf("%13.2f %9.2f %9.2f %9.2f", payments[0], payments[1], payments[2], payments[3]);
}
Here is what it outputs (note: there is other code that prints out the top portion of the output) :
Years: 15 20 25 30
__________________________________________________
3.0% 421.60 0.00 0.00 0.00
There is obviously a math error in here somewhere which is really bugging me because I passed the exact same parameters earlier and it was returning correct values.
What I am concerned with is that there are no values being placed in the last three indices. Can anyone explain to me what I have done wrong here?
P.S. Here is the LoanCalculator method I am using:
public static double LoanCalculator(double loan, double rate, int payments)
{
double r = rate/12;
double monPay = (loan * r * Math.pow(1+r, payments))/((Math.pow(1+r, payments))-1);
return monPay;
}
Any help is appreciated.
You are setting your index to 0 inside the loop. So only the first item is ever assigned.
You probably need:
int index = 0;
for (int year = 15; year <= 30; year += 5) {
payments[index++] = calculateLoan(initLoan, rate, year * 12);
}
Or better (in my opinion):
for (int i = 0; i < payments.length; i++) {
int year = i * 15;
int month = year * 12;
payments[i] = calcualteLoan(initLoan, rate, month);
}
Consider this code
for(int i = 15; i <= 30; i += 5){
double rate = 0.03;
int index = 0;
within your for loop your are re-setting index to zero each time
so the effect of
index++;
is nullified
Move the declaration of index to before your for loop
double rate = 0.03;
int index = 0;
for(int i = 15; i <= 30; i += 5){
payments[index++] = LoanCalculator(initLoan, rate, i*12);
}
You set index to 0 in your for-loop. This makes the loop reset the index each time you call it. The way to fix this would be to instantiate index above the loop and increment in the loop.

Given an array of time and selling price find the best buying and selling time to maximize the profit

Given [ (02:00, 7.5), (03:30, 7.9), (04:00, 8.0), (05:30, 6.8), (10:00, 9.01)] times and selling price we need to find the best time for buying and selling to maximize the profit.
// times are in increasing order
// Sample Output: Buy at 05:30 and sell at 10:00 for a profit of 2.21
I have written the logic to find the max profit but I also need to find the best buying and selling time, so I am bit stuck there
double profit(double prices[])
{
double maxprofit=0;
for(int i=0;i<price.length;i++)
{
double min= values[i];
for(int j=i+1;j<price.length;j++)
{
if(price[j]<price[min])
min=values[min];
}
profit=values[i]-min;
if(maxprofit<profit)
maxprofit=profit;
else
continue;
}
There is no need to use a nested loop, there is a linear time algorithm that can solve this problem.
There is a very detailed explanation of the algorithm here.
Here is how you could fix your code:
public double maxProfit(double[] prices) {
if (prices.length <= 1) return 0;
double minPrice = prices[0];
double maxSoFar = Integer.MIN_VALUE;
double profitSoFar = Integer.MIN_VALUE;
for (int i = 1; i < prices.length; i++){
profitSoFar = prices[i] - minPrice;
minPrice = Math.min(minPrice, prices[i]);
maxSoFar = Math.max(profitSoFar, maxSoFar);
}
return Math.max(maxSoFar, 0);
}

Calculating Compound Interest without math.pow in java

I need to calculate the monthly compounding interest in a savings account that is getting a monthly deposit. The variables I have to work with:
monthly savings ( Eg. I deposit $125.75 each month)
months (Eg. I deposit the same for 15 months)
APR (the ANNUAL interest is 5.65%)
Now I need to calculate the total savings amount, which for the given numbers here, the final answer should be $1958.88.
In essence, I am working with A = P(1 + r/12)^(12*t), where P is the amount I deposit * months, r is the APR, and t is the months/12 to get the "how many years"
The catch here is that I can not use the math.pow() as a requirement on the assignment, so my best guess is that I am to calculate it with a for/while loop similar to the following:
public static void main(String[] args)
{
double monthlySavings = 125.75;
double APR = 5.65;
int months = 15;
int monthCount = 0;
double totalSavings = 0;
while (monthCount < months)
{
totalSavings += monthlySavings + (1+APR/12/100);
mothCount++;
}
System.out.printf("Your total savings will be $%.2f\n", totalSavings);
}
The above code is NOT the correct solution, but its the closest i've come. The problem is that I am applying the interest to the monthly savings each time before it accumulates to the total. eg. it adds 125.75*interest for 15 deposits. What it SHOULD do is start with 125.75*interest then add 125.75, and then take the interest of the amount you have total so far, then add 125.75 and take the interest of the total amount again, and so on for the amount of months.
This is probably a lot easier than I am making it out to be, but I have tried for hours with adding different placeholder variables, but I am lacking some crucial concept, please help!
A loop for the number of months
for (int monthNumber = 0; monthNumber < numberOfMonths; monthNumber++)
{
}
then for each each month, add the interest then add the monthly savings. In that order, the other way around you end up with interest on money you just deposited, which is wrong.
totalSavings *= (APR / 12 / 100); //Although I would have separate variable for this
totalSavings += monthlySavings;
you don't really need to keep a month count but I prefer for loops.
After re-reading my question, I had an epiphany.. As I originally thought, the answer was a lot easier than I was making it out to be.
public static void main(String[] args)
{
double monthlySavings = 125.75;
double APR = 5.65;
int months = 15;
int monthCount = 0;
double placeHolder = 0;
double totalSavings = 0;
while (monthCount < months)
{
placeHolder += monthlySavings;
totalSavings = placeHolder * (1+APR/12/100);
placeHolder = totalSavings;
monthCount++;
}
System.out.printf("Your total savings will be $%.2f", totalSavings);
}

What is sum of squares when it comes to variance (calculation in Java)?

Summary: Program asks user to enter their number of shoes (0-200). Once they type in a non-number, calculations are made.
Variables made are:
int numberOfShoes =0;int highNumber = 0;
int lowNumber = 0;
int sumofShoesInputted = 0;
int sumOfSquares = 0;
double mean = 0;
double variance = 0;
double standardDeviation = 0;
The formula for variance for a part of my program is:
variance = (sumofTheSquares - (sumOfShoesInputted*sumOfShoesInputted / numberOfShoes)) / numberOfShoes -1)
for standard deviation it's
Math.sqrt(variance);
I'm just confused what exactly is the "sum of the squares" part.
*Would also like to add that the formula was given to me.
**Even though it's homework I'm completely confused by this ONE thing. I'm not asking you to write my program. Just asking for a simple explanation.
The sum of the squares of a set of numbers A1, A2, ... ,AN
is the expression A1*A1 + A2*A2 + ... + AN*AN. This is what
is meant here.

Calculating Standard Deviation of Angles?

So I'm working on an application using compass angles (in degrees). I've managed to determine the calculation of the mean of angles, by using the following (found at http://en.wikipedia.org/wiki/Directional_statistics#The_fundamental_difference_between_linear_and_circular_statistics) :
double calcMean(ArrayList<Double> angles){
double sin = 0;
double cos = 0;
for(int i = 0; i < angles.size(); i++){
sin += Math.sin(angles.get(i) * (Math.PI/180.0));
cos += Math.cos(angles.get(i) * (Math.PI/180.0));
}
sin /= angles.size();
cos /= angles.size();
double result =Math.atan2(sin,cos)*(180/Math.PI);
if(cos > 0 && sin < 0) result += 360;
else if(cos < 0) result += 180;
return result;
}
So I get my mean/average values correctly, but I can't get proper variance/stddev values. I'm fairly certain I'm calculating my variance incorrectly, but can't think of a correct way to do it.
Here's how I'm calculating variance:
double calcVariance(ArrayList<Double> angles){
//THIS IS WHERE I DON'T KNOW WHAT TO PUT
ArrayList<Double> normalizedList = new ArrayList<Double>();
for(int i = 0; i < angles.size(); i++){
double sin = Math.sin(angles.get(i) * (Math.PI/180));
double cos = Math.cos(angles.get(i) * (Math.PI/180));
normalizedList.add(Math.atan2(sin,cos)*(180/Math.PI));
}
double mean = calcMean(angles);
ArrayList<Double> squaredDifference = new ArrayList<Double>();
for(int i = 0; i < normalizedList.size(); i++){
squaredDifference.add(Math.pow(normalizedList.get(i) - mean,2));
}
double result = 0;
for(int i = 0; i < squaredDifference.size(); i++){
result+=squaredDifference.get(i);
}
return result/squaredDifference.size();
}
While it's the proper way to calculate variance, I'm not what I'm supposed to use. I presume that I'm supposed to use arctangent, but the standard deviation/variance values seem off. Help?
EDIT:
Example: Inputting the values 0,350,1,0,0,0,1,358,9,1 results with the average angle of 0.0014 (since the angles are so close to zero), but if you just do a non-angle average, you'll get 72...which is way off. Since I don't know how to manipulate individual values to be what they should be, the variance calculated is 25074, resulting in a standard deviation of 158 degrees, which is insane!! (It should only be a few degrees) What I think I need to do is properly normalize individual values so I can get correct variance/stddev values.
By the Wikipedia page you link to the circular standard deviation is sqrt(-log R²), where R = |mean of samples|, if you consider the samples as complex numbers on the unit circle. So the calculation of standard deviation is very similar to the calculation of the mean angle:
double calcStddev(ArrayList<Double> angles){
double sin = 0;
double cos = 0;
for(int i = 0; i < angles.size(); i++){
sin += Math.sin(angles.get(i) * (Math.PI/180.0));
cos += Math.cos(angles.get(i) * (Math.PI/180.0));
}
sin /= angles.size();
cos /= angles.size();
double stddev = Math.sqrt(-Math.log(sin*sin+cos*cos));
return stddev;
}
And if you think about it for a minute it makes sense: When you average a bunch of points close to each other on the unit circle the result is not too far off from the circle, so R will be close to 1 and the stddev near 0. If the points are distributed evenly along the circle their average will be close to 0, so R will be close to 0 and the stddev very large.
When you use Math.atan(sin/cosine) you get an angle between -90 and 90 degrees. If you have 120 degrees angle, you get cos=-0.5 and sin=0.866, then you get atan(-1.7)=-60 degrees. Thus you put wrong angles in your normalized list.
Assuming that variance is a linear deviation, I'd recommend you to rotate your angles array by the -calcMean(angles) and add/subtract 360 to/from angles above/below 180/-180 (damn my writing!)) while finding maximum and minimum angle. It will give you desired deviations. Like this:
Double meanAngle = calcMean(angles)
Double positiveDeviation = new Double(0);
Double negativeDeviation = new Double(0);
Iterator<Double> it = angles.iterator();
while (it.hasNext())
{
Double deviation = it.next() - meanAngle;
if (deviation > 180) deviation -= 180;
if (deviation <= -180) deviation += 180;
if (deviation > positiveDeviation) positiveDeviation = deviation;
if (deviation > negativeDeviation) negativeDeviation = deviation;
}
return positiveDeviation - negativeDeviation;
For average squared deviations you should use your method (with angles, not "normalized" ones), and keep looking for (-180, 180) range!
The math library function remainder is handy for dealing with angles.
A simple change would be to replace
normalizedList.get(i) - mean
with
remainder( normalizedList.get(i) - mean, 360.0)
However your first loop is then redundant, as the call to remainder will take care of all the normalisation. Moreover it's simpler just to sum up the squared differences, rather than store them. Personally I like to avoid pow() when arithmetic will do. So your function could be:
double calcVariance(ArrayList<Double> angles){
double mean = calcMean(angles);
double result = 0;
for(int i = 0; i < angles.size(); i++){
double diff = remainder( angles.get(i) - mean, 360.0);
result += diff*diff;
}
return result/angles.size();
}
The current good way to deal with this is now the two functions already implemented in scipy :
circmean : https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.circmean.html
circstd : https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.circstd.html
Couple of great things included :
vectorization for fast computing
nan dealing
high, low thresholds, typically for angles between 0 and 360 degrees vs between 0 and 2 Pi.
The accepted answer by Joni does an excellent job at answering this question, but as Brian Hawkins noted:
Mind the units. The function as written takes angles in degrees as input and returns the standard deviation in radians.
Here's a version that fixes that issue by using degrees for both its arguments and its return value. It also has more flexibility, as it allows for a variable number of arguments.
public static double calcStdDevDegrees(double... angles) {
double sin = 0;
double cos = 0;
for (int i = 0; i < angles.length; i++) {
sin += Math.sin(angles[i] * (Math.PI/180.0));
cos += Math.cos(angles[i] * (Math.PI/180.0));
}
sin /= angles.length;
cos /= angles.length;
double stddev = Math.sqrt(-Math.log(sin*sin+cos*cos));
return Math.toDegrees(stddev);
}

Categories