How to calculate the Median Absolute Deviation (MAD) in Java from a list (e.g. List<Double> list)?
I found some implementations on stackoverflow in programming languages I don't know (e.g. in C# and in R) but none of them is in Java.
To calculate median:
You can use Arrays.sort() to sort the input array, then if arrayLength%2==0 then median value is (array[array.length/2-1] + array[array.length/2])/2 otherwise the median is (array[array.length/2]).
To calculate MAD:
Create Double[] intermediate - new Double[array.length] and calculate the intermediate array using intermediate[i] = Math.abs(input[i]-median) for each element, then calculate the median for the intermediate array same way as in the first step and you're ready.
Example I've made for you:
import java.util.Arrays;
import java.util.List;
public class MAD {
public static void main(String[] args) {
List<Double> input = Arrays.asList(new Double[] {1d, 1d, 2d, 2d, 4d, 6d, 9d});
System.out.println(mad(input));
}
private static Double mad(List<Double> inputList) {
Double[] input = inputList.toArray(new Double[inputList.size()]);
Double median = median(input);
arrayAbsDistance(input, median);
return median(input);
}
private static void arrayAbsDistance(Double[] array, Double value) {
for (int i=0; i<array.length;i++) {
array[i] = Math.abs(array[i] - value);
}
}
private static Double median(Double[] input) {
if (input.length==0) {
throw new IllegalArgumentException("to calculate median we need at least 1 element");
}
Arrays.sort(input);
if (input.length%2==0) {
return (input[input.length/2-1] + input[input.length/2])/2;
}
return input[input.length/2];
}
}
Related
Hello I am new to java so please be gentle,
class Result{
public float Mean(){
//find the mean of the array
}
public float lowest(){
// find the lowest
}
}
public class Main{
public static void main(String[] args) {
float arr[] = {1.1,2.2,3.3};
}
}
What I want to do is to take the array arr from Main, and bring it to class Result so that I can use it
in Mean() and Lowest().
Thank you.
Try add the array as part of constructor of Result/Solve, then you could work with numbers inside the instance you create.
class Solve {
final float[] numbers;
public Result(final float[] numbers){
this.numbers = numbers;
}
public float mean(){
//find the mean using the this.numbers
}
public float lowest(){
// find the lowest using this.numbers
}
}
public class Main{
public static void main(String[] args) {
float numbers[] = new float[]{1.1,2.2,3.3};
Solve solve = new Solve(numbers);
float mean = solve.mean();
float lowest = solve.lowest();
System.out.println("Mean: " + mean);
System.out.println("Lowest: " + lowest);
}
}
Another option is to make your methods static and pass the numbers as part of the methods, similar to Math class.
class Solve {
public static float mean(float[] numbers){
}
public static float lowest(float[] numbers) {
}
}
public class Main{
public static void main(String[] args) {
float numbers[] = new float[]{1.1,2.2,3.3};
float mean = Solve.mean(numbers);
float lowest = Solve.lowest(numbers);
System.out.println("Mean: " + mean);
System.out.println("Lowest: " + lowest);
}
}
Here's how I would handle this:
Result class:
class Result {
public static float mean(float... arr) { //make the method static, and have it take the array as a parameter
float sum = 0f;
for (float f : arr) { //add each number in the array to the sum variable
sum += f;
}
return sum / arr.length; //return sum / length, which is average
}
public static float lowest(float... arr) { //same as the above method
float lowest = arr[0];
for (float f : arr) { //loop through the array
if (f < lowest) { //if this number is lower than the current "lowest" number, set lowest to be this number
lowest = f;
}
}
return lowest; //return the lowest number
}
}
Main class:
public class Main {
public static void main(String[] args) {
float[] arr = new float[] { 1.1f, 2.2f, 3.3f }; //here's the array
System.out.println(Result.mean(arr)); //I pass it to the method as a parameter
System.out.println(Result.lowest(arr)); //same here
}
}
An alternative solution would be to use Java streams instead of for loops. Java streams can get more complicated than for loops, but they can be much cleaner and easier to read. Here's how I would rewrite the Result class using streams:
class Result {
public static float mean(float... arr) {
return (float) IntStream.range(0, arr.length)
.mapToDouble((i) -> arr[i])
.average()
.getAsDouble(); //returns the average of the array
}
public static float lowest(float... arr) {
return (float) IntStream.range(0, arr.length)
.mapToDouble((i) -> arr[i])
.min()
.getAsDouble(); //returns the minimum value in the array
}
}
Pass your array as an argument to the other object’s method.
float[] arr = { 1.1F, 2.2F, 3.3F } ;
Result r = new Result() ;
float output = r.lowest( arr ) ;
Define that argument on the method.
class Result{
public float mean( float[] input ){
// … find the mean of the array
}
public float lowest( float[] input ){
// … find the lowest
}
}
See this code run live at IdeOne.com.
Passing an argument/parameter to a method is a basic minimal skill in Java. You should study the Java Tutorials by Oracle, and consult a textbook to get the basics down.
import java.util.ArrayList;
public class Testing {
public static void main(String[] args) {
ArrayList<Double> valid = new ArrayList<Double>();
ArrayList<Double> result = new ArrayList<Double>();
valid.add(0.05);
valid.add(0.05);
valid.add(0.1);
getSum(valid, result, 0, 0);
System.out.println(result);
}
public static void getSum(ArrayList<Double> valid, ArrayList<Double> result, int start, double sum) {
if (valid.size() == start) {
result.add(sum);
return;
}
double value = sum + valid.get(start);
getSum(valid, result, start + 1, value);
getSum(valid, result, start + 1, sum);
}
}
I want to not even enter the duplicates into the result arrayList, as removing duplicates after will result in not enough memory, as the result arrayList gets too big too fast. How do I do this?
Edit: A hashset suffices.
Using interfaces gives greater code universality,
in java 8, you can use stream and method distinct():
List<Double> valid = new ArrayList<>();
valid.add(0.05);
valid.add(0.05);
valid.add(0.1);
List<Double> removedDuplicates = valid.stream().distinct().collect(Collectors.toList());
I ended up using a set instead of an ArrayList like Kon and Sam_ferree suggested. This ended up working:
import java.util.ArrayList;
import java.util.Set;
import java.util.TreeSet;
public class Testing {
public static void main(String[] args) {
ArrayList<Double> valid = new ArrayList<Double>();
Set<Double> result = new TreeSet<Double>();
valid.add(0.05);
valid.add(0.05);
getSum(valid, result, 0, 0);
System.out.println(result);
}
public static void getSum(ArrayList<Double> valid, Set<Double> result, int start, double sum) {
if (valid.size() == start) {
result.add(sum);
return;
}
double value = sum + valid.get(start);
getSum(valid, result, start + 1, value);
getSum(valid, result, start + 1, sum);
}
}
Use a Set instead of a List, like HashSet or TreeSet
Sets by definition don't allow duplicates, so changing that datatype is the only change your code needs.
I'm doing something that produces the right result. However, it is wrong from a design POV.
The point of the program is to list the result of all the powers of a number up to and including the user-defined limit.
I have a constructor which accepts the base and the exponent from the Scanner. Then a method, which utilises a for loop to calculate the power for each exponent.
Now, the problem is that I'm printing the result from each loop iteration directly from this method. This beats the point of private variables and it being void in the 1st place.
Therefore, I want to define a getter method which returns the result of each power to the output. I used to set them just fine for if/switch statements, but I don't know how to do the same for loops. If I assign the result to a variable within the loop and return that variable from the getter then it will return only the output from the final iteration.
Private implementation
package Chapter6Review;
public class Powers {
private int target;
private int power;
public Powers(int target, int power) {
this.target = target;
this.power = power;
}
public void calculatePower() {
for (int i = 0; i <= power; i++) {
System.out.println((int) Math.pow(target, i));
}
}
/*
public int getPower() {
return
}
*/
}
User interface
package Chapter6Review;
import java.util.Scanner;
public class PowersTester {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Enter your base: ");
int target = in.nextInt();
System.out.print("Enter your exponent: ");
int power = in.nextInt();
Powers tester = new Powers(target, power);
tester.calculatePower();
}
}
You can simply use a List ;
public List<Integer> calculatePower() {
int p;
List<Integer> result = new ArrayList<Integer>();
for (int i = 0; i <= power; i++) {
p = (int) Math.pow(target, i);
result.add(p);
}
return result;
}
Then in you main method, you can iterate the list to print the powers like that :
List<Integer> result = new ArrayList<Integer>();
Powers tester = new Powers(target, power);
result = tester.calculatePower();
for (int i = 0; i < result.size(); i++) {
System.out.println(result.get(i));
}
You could store each of the results in a List:
List<Power> list = new ArrayList<>();
and when you call it add it as well
list.add(new Powers(target, power));
At the end you can iterate over the list like this:
for (Power power : list){
// your code
}
You might consider using streams as well
public List<Integer> calculatePower() {
return IntStream
.rangeClosed(0, power). // iterate from 0 till power inclusive
.mapToObj(i -> (int) Math.pow(target,i))
.collect(Collectors.toList()); // get result as list
}
Thanks for all the answers. Using a list seems to be a good choice.
Since I haven't covered lists yet, I resorted to this solution for now. But I don't like having code that can affect the solution in the main. Ideally, the loop should go in the private implementation.
Main
Powers tester = new Powers(target, power);
for (int i = 0; i <= power; i++) {
tester.calculatePower(i);
System.out.println(tester.getPower());
}
Private implementation
public void calculatePower(int iPower) {
result = (int) Math.pow(target, iPower);
}
public int getPower() {
return result;
}
So I'm trying to write a recursive method to sum an arraylist of integers and create a client to test it.
My Class is:
import java.util.ArrayList;
public class SumArray
{
public static int ArraySum(int[]arrayList, int sum, int size)
{
sum = sum + arrayList[size];
size--;
while(size >= 0)
{
return ArraySum(arrayList, sum, size);
}
return sum;
}
}
My Client is:
import java.util.ArrayList;
public class ArraySumClient
{
public static void main()
{
System.out.print("The sum of the array is: ");
SumArray r = new SumArray();
int[] myList = new int[5];
myList[0] = 1;
myList[1] = 2;
myList[2] = 3;
myList[3] = 4;
int size = myList.length-1;
System.out.println(r.ArraySum(myList, 0, size));
}
}
These both compile and work. However, I'm trying to figure out a way for the user to input the size of the array and the numbers in the array instead of my inputting the array size and numbers inside the client.
you can use java scanner to take input from cmd prompt
https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html
You could try using an ArrayList instead of an array. It would let you dynamically add as many items as needed:
public static void main() {
List<Integer> myList = new ArrayList<Integer>();
myList.add(1);
myList.add(2);
myList.add(3);
myList.add(4);
// compute sum
int sum = 0;
for (Integer value : myList) {
sum += value;
}
System.out.println("The sum is " + sum);
}
Using this approach, you would not need to ask how many items the user intends to add.
As #Satya suggested, you could read input from the command line as command line argument and extract them as:
Integer[] array = Stream.of(args).map(Integer::parseInt).toArray(size -> new Integer[size]);
You do not want to pass the length of the array to the method ArraySum which, I suppose you are doing because you are not able to remove an element from the array. One way of doing this is by using Arrays.copyOf() using which you could copy a part of the array as another array.
I think it is always good to use List of theses situations.
In fact, I want to use "normOfVector()" method with Integer, and Float, but I couldn't
I get this error:
The method normOfVector(ArrayList) in the type TestMethod is not applicable for the arguments (ArrayList)
package code;
import java.util.ArrayList;
import java.util.List;
public class TestMethod
{
public static float normOfVector(ArrayList<Integer> list)
{
float sum = 0.0f;
for (Integer i : list)
sum = sum + (float) (i * i);
// end for
return (float) Math.sqrt(sum);
}// end function
public static void main(String[] args)
{
// In this case no Problem
ArrayList<Integer> listI = new ArrayList<>();
listI.add(0);
listI.add(3);
listI.add(5);
listI.add(7);
listI.add(2);
float result = normOfVector(listI);
// In this case will not work
ArrayList<Float> listF = new ArrayList<>();
listF.add(0.0f);
listF.add(3.0f);
listF.add(5.0f);
listF.add(7.0f);
listF.add(2.0f);
result = normOfVector(listF);
}// end main
}// end class
My point is:
I want to create a method that accept the two cases.
Thank you.
In your first block your are computing numbers but storing them as objects. You should be storing them as Integer or Float, or maybe Double or Number, but not Object. Second in your cos(...) method you should limit what kind of parameters are accepted by changing the declaration to List<Integer>, List<Float> or List<? extends Number>. It may help to study up on java generics and especially using the PECS principle.
Based on your updated code.
public class TestMethod {
public static double normOfVector(List<? extends Number> list) {
double sum = 0.0;
for (Number d : list)
sum += d.doubleValue() * d.doubleValue();
return Math.sqrt(sum);
}
public static void main(String[] args) {
List<Integer> listI = new ArrayList<>();
listI.add(0);
listI.add(3);
listI.add(5);
listI.add(7);
listI.add(2);
double result = normOfVector(listI);
List<Float> listF = new ArrayList<>();
listF.add(0.0f);
listF.add(3.0f);
listF.add(5.0f);
listF.add(7.0f);
listF.add(2.0f);
result = normOfVector(listF);
}
}
This is how I would write it using List<Double>
Map<String, Double> currentWord = new HashMap<>();
double first = main.getWords().get(firstWord);
for(Map.Entry<String, Double> entry : main.getWords()) {
String secondWord = entry.getValue();
double cosValue = vectors.cos(first, entry.getValue());
if (cosValue >= percentage) {
currentWord.put(secondWord, Math.round(cosValue * 100) / 100.0);
break; // is there any point searching for another word?
}
}
Maybe you can also use something like this:
Number[] numbers = new Number[] { valueOfFloat, valueOfInteger };