Adjust list by normalizing in java - java

When analysing data sets, such as data for human heights or for human weights, a common step is to adjust the data. This adjustment can be done by normalizing to values between 0 and 1, or throwing away outliers.
For this program, adjust the values by dividing all values by the largest value. The input begins with an integer indicating the number of floating-point values that follow. Assume that the list will always contain fewer than 20 floating-point values.
Output each floating-point value with two digits after the decimal point, which can be achieved as follows:
System.out.printf("%.2f", yourValue);
Ex: If the input is:
5 30.0 50.0 10.0 100.0 65.0
the output is:
0.30 0.50 0.10 1.00 0.65
The 5 indicates that there are five floating-point values in the list, namely 30.0, 50.0, 10.0, 100.0, and 65.0. 100.0 is the largest value in the list, so each value is divided by 100.0.
For coding simplicity, follow every output value by a space, including the last one.
This is my code so far:
import java.util.Scanner;
public class LabProgram {
public static void main(String[] args) {
Scanner scnr = new Scanner(System.in);
double numElements;
numElements = scnr.nextDouble();
double[] userList = new double[numElements];
int i;
double maxValue;
for (i = 0; i < userList.length; ++i) {
userList[i] = scnr.nextDouble();
}
maxValue = userList[i];
for (i = 0; i < userList.length; ++i) {
if (userList[i] > maxValue) {
maxValue = userList[i];
}
}
for (i = 0; i < userList.length; ++i) {
userList[i] = userList[i] / maxValue;
System.out.print(userList[i] + " ");
System.out.printf("%.2f", userList[i]);
}
}
}
I keep getting this output.
LabProgram.java:8: error: incompatible types: possible lossy conversion from double to int
double [] userList = new double [numElements];
^
1 error
I think my variable is messed up. I read through my book and could not find help. Can someone please help me on here. Thank you so much! This has been very stressful for me.

The specific error message is because the index and size of an element must be int. So declare and assign at once: int numElements = scnr.nextInt();

Better way of programming things:
skip manual input (aka Scanner and consorts). Makes you crazy and testing a 100'000'000 times slower
you can integrate the interactive part later, once the method is done. You already know how, your code already shows.
use an explicit method to do your work. Don't throw everything into the main method. This way you can run multiple examples/tests on the method, and you have a better implementation for later.
check for invalid input INSIDE the method that you implement. Once you can rely in such a method, you can keep on using it later on.
you could even move the example numbers to its own test method, so you can run multiple test methods. You will learn about Unit Testing later on.
Example code:
public class LabProgram {
public static void main(final String[] args) {
final double[] initialValues = new double[] { 30.0, 50.0, 10.0, 100.0, 65.0 };
final double[] adjustedValues = normalizeValuesByHighest(initialValues);
System.out.println("Adjusted values:");
for (final double d : adjustedValues) {
System.out.printf("%.2f ", Double.valueOf(d));
}
// expected otuput is 0.30 0.50 0.10 1.00 0.65
System.out.println();
System.out.println("All done.");
}
static public double[] normalizeValuesByHighest(final double[] pInitialValues) {
if (pInitialValues == null) throw new IllegalArgumentException("Invalid double[] given!");
if (pInitialValues.length < 1) throw new IllegalArgumentException("double[] given contains no elements!");
// detect valid max value
double tempMaxValue = -Double.MAX_VALUE;
boolean hasValues = false;
for (final double d : pInitialValues) {
if (Double.isNaN(d)) continue;
tempMaxValue = Math.max(tempMaxValue, d);
hasValues = true;
}
if (!hasValues) throw new IllegalArgumentException("double[] given contains no valid elements, only NaNs!");
// create return array
final double maxValue = tempMaxValue; // final from here on
final double[] ret = new double[pInitialValues.length];
for (int i = 0; i < pInitialValues.length; i++) {
ret[i] = pInitialValues[i] / maxValue; // NaN will stay NaN
}
return ret;
}
}
Output:
Adjusted values:
0,30 0,50 0,10 1,00 0,65
All done.

Related

Optimisation in Java Using Apache Commons Math

I'm trying to minimise a value in Java usingcommons-math. I've had a look at their documentation but I don't really get how to implement it.
Basically, in my code below, I have a Double which has the expected goals in a soccer match and I'd like to optimise the probability value of under 3 goals occurring in a game to 0.5.
import org.apache.commons.math3.distribution.PoissonDistribution;
public class Solver {
public static void main(String[] args) {
final Double expectedGoals = 2.9d;
final PoissonDistribution poissonGoals = new PoissonDistribution(expectedGoals);
Double probabilityUnderThreeGoals = 0d;
for (int score = 0; score < 15; score++) {
final Double probability =
poissonGoals.probability(score);
if (score < 3) {
probabilityUnderThreeGoals = probabilityUnderThreeGoals + probability;
}
}
System.out.println(probabilityUnderThreeGoals); //prints 0.44596319855718064, I want to optimise this to 0.5
}
}
The cumulative probability (<= x) of a Poisson random variable can be calculated by:
In your case, x is 2 and you want to find lambda (the mean) such that this is 0.5. You can type this into WolframAlpha and have it solve it for you. So rather than an optimisation problem, this is just a root-finding problem (though one could argue that optimisation problems are just finding roots.)
You can also do this with Apache Commons Maths, with one of the root finders.
int maximumGoals = 2;
double expectedProbability = 0.5;
UnivariateFunction f = x -> {
double sum = 0;
for (int i = 0; i <= maximumGoals; i++) {
sum += Math.pow(x, i) / CombinatoricsUtils.factorialDouble(i);
}
return sum * Math.exp(-x) - expectedProbability;
};
// the four parameters that "solve" takes are:
// the number of iterations, the function to solve, min and max of the root
// I've put some somewhat sensible values as an example. Feel free to change them
double answer = new BisectionSolver().solve(Integer.MAX_VALUE, f, 0, maximumGoals / expectedProbability);
System.out.println("Solved: " + answer);
System.out.println("Cumulative Probability: " + new PoissonDistribution(answer).cumulativeProbability(maximumGoals));
This prints:
Solved: 2.674060344696045
Cumulative Probability: 0.4999999923623868

Java Euler number result infinity

I try to use a recursive function to calculate the Euler number in Java. It's OK when I enter small numbers into this formula:
But when I try to enter a bigger number like 1000 I get infinity.
Why it's happening. How I can fix it.
import java.util.Scanner;
public class enumber {
public static long fact(int a) {
if(a <= 1) {
return 1;
}
return a * fact(a - 1);
}
public static double calculate(int i) {
double cresult = Math.pow(fact(i), -1);
if(i == 0 ) {
return 1;
}
return cresult+calculate(i-1);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter i value: ");
int i = sc.nextInt();
double eresult = calculate(i);
System.out.println(eresult);
}
}
output;
Enter i value:
1000
Infinity
That's because you try to calculate the factorial of 1000....which is pretty huge.
Factorial 1000
You try to store it in a long value, but long's
max value is way smaller than 1000!. It basically doesn't fit anymore.
Consider using the class BigInteger (or BigDecimal), its in the default java sdk and you can directly output via println().
However you know the result already, its e, so you might only need to implement the Big-Class for the factorial.
You are exceeding the capacity of a long. But I would suggest you decide how much precision you want for e.
Let's say you want it to have an error of less than .0000001. Continue the iteration for e until the positive delta between your latest computation and the previous is less than or equal to your error.
If you want to take it to extremes, you can always use BigDecimal to increase the accuracy of your results.
I solved that problem by using loops. And for the old algorithm, I changed the fact method type to double. I get rid of Infinity. After that, I face "StackOverflowError".
What is a StackOverflowError?
My new algorithm is;
import java.util.Scanner;
public class enumber2 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
double fact;
double eNumber = 0;
int i = in.nextInt();
while(i>0) {
fact=1;
for(int j=1; j<=i; j++) {
fact = fact * j;
}
eNumber = eNumber +(1.0/fact);
i--;
}
eNumber = eNumber +1;
System.out.println(eNumber);
}
}
even I enter big numbers after a little bit of patient I'm getting results without exception.

How to make a randomness checker more efficient

Hello I'm trying to make a program to check the distribution of random numbers in Java.
The idea of the program is to (using Java) generate many random numbers and then see how many numbers are in each of the following ranges:
0.0 - 0.1
0.1 - 0.2
0.2 - 0.3
...
0.8 - 0.9
0.9 - 1.0
I have managed to do this but I was wondering if there is a more efficient/quicker way to do it.
public class RandomTest
{
//Get value of digit in tenths place of double
public static int getFirstDecimal(double num)
{
return (int) (num * 10);
}
public static void main(String args[])
{
int[] results = new int[10]; //Results array
double x; //Random number holder
int genNum; //Number of random numbers to generate
for(genNum = 0; genNum < 10000; genNum++)
{
x = Math.random();
results[getFirstDecimal(x)]++;
}
for(int i = 0; i < 10; i++)
{
System.out.println(results[i]);
}
}
}
Try this if you really want to shorten the code:
int[] results = new int[10];
IntStream.range(1, 10000).forEach(s -> results[getFirstDecimal(Math.random())]++);
Arrays.stream(results).forEach(System.out::println);
IntStream from 1 to 10000 is just like a for-loop, and for each of those numbers you do the same thing you did, increment value at corresponding index in an array. Then you just print that array, also using streams. Ofcourse you need to keep your getFirstDecimal method, because this code is using this method inside, you could extract code from that method to the stream, but it would look ugly, I think it's better to have a separate method for that.

Creating 0.000.. with certain decimals

I am trying to create the number 0.00000.... with as many '0' as the user input wants. What is wrong with my code below?
int n;
double dec = 0.0;
in = new Scanner(System.in);
n = in.nextInt();
for (i = 1; i <= n; i++)
dec = dec / 10.0d;
Number doesn't change.
You're expecting double to retain the number of decimal digits - it doesn't do that. The value is always normalized. The double type is all about the magnitude of a number, not a particular decimal representation. It's suitable for naturally occurring quantities - weights, heights etc.
If you care about decimal digits, then BigDecimal is a more suitable type for you. This is more appropriate for currency values for example, where there really is a precise amount specified as a decimal representation.
BigDecimal does retain the number of decimal digits you use, but you'll need to be careful about exactly how you use it. You'll no doubt find the setScale method useful.
For example:
import java.math.BigDecimal;
class Test {
public static void main(String[] args) throws Exception {
BigDecimal x = new BigDecimal("0")
System.out.println(x); // 0
x = x.setScale(5);
System.out.println(x); // 0.00000
}
}
If you just want to display the decimal point according to user input, Try
int n;
double dec = 0.0;
in = new Scanner(System.in);
n = in.nextInt(); //number of decimal places
System.out.println(String.format("%."+n+"f",dec));
0.0, 0.00, 0.0000000000000000000000000000000000000000000000 and so on are exactly the same value; Java literally can't tell them apart during runtime. No matter how many times you divide it by 10, it will remain EXACTLY the same number.
When being printed, trailing zero digits are omitted (unless explicitly specified in, for instance, String.format).
Basically, what you are trying to do is keep on dividing 0.0. But it'll always give you the same result as Java considers 0.000 as 0.0. Even 0.0000000000000000 will be considered as 0.0. If you just want to display that many 0s, then save it in a String and then display.
...
StringBuilder s = new StringBuilder("0.");
for(int i = 1; i < n; i++)
s.append("0");
String num = s.toString();
//Then use it.
If you need string with user defined '0':
public static String FormatZero( int accurancy_ ) throws IllegalArgumentException
{
if( 0 >= accurancy_ )
{
throw new IllegalArgumentException( "accurancy_must be > 0" );
}
String formatString = "0.";
for( int i = 0 ; i < accurancy_ ; ++i )
{
formatString += "0";
}
DecimalFormat format = new DecimalFormat( formatString );
String result = format.format( 0d );
return result;
}

Check if a number is a double or an int

I am trying to beautify a program by displaying 1.2 if it is 1.2 and 1 if it is 1 problem is I have stored the numbers into the arraylist as doubles. How can I check if a Number is a double or int?
Well, you can use:
if (x == Math.floor(x))
or even:
if (x == (long) x) // Performs truncation in the conversion
If the condition is true, i.e. the body of the if statement executes, then the value is an integer. Otherwise, it's not.
Note that this will view 1.00000000001 as still a double - if these are values which have been computed (and so may just be "very close" to integer values) you may want to add some tolerance. Also note that this will start failing for very large integers, as they can't be exactly represented in double anyway - you may want to consider using BigDecimal instead if you're dealing with a very wide range.
EDIT: There are better ways of approaching this - using DecimalFormat you should be able to get it to only optionally produce the decimal point. For example:
import java.text.*;
public class Test
{
public static void main(String[] args)
{
DecimalFormat df = new DecimalFormat("0.###");
double[] values = { 1.0, 3.5, 123.4567, 10.0 };
for (double value : values)
{
System.out.println(df.format(value));
}
}
}
Output:
1
3.5
123.457
10
Another simple & intuitive solution using the modulus operator (%)
if (x % 1 == 0) // true: it's an integer, false: it's not an integer
I am C# programmer so I tested this in .Net. This should work in Java too (other than the lines that use the Console class to display the output.
class Program
{
static void Main(string[] args)
{
double[] values = { 1.0, 3.5, 123.4567, 10.0, 1.0000000003 };
int num = 0;
for (int i = 0; i < values.Length; i++ )
{
num = (int) values[i];
// compare the difference against a very small number to handle
// issues due floating point processor
if (Math.Abs(values[i] - (double) num) < 0.00000000001)
{
Console.WriteLine(num);
}
else // print as double
{
Console.WriteLine(values[i]);
}
}
Console.Read();
}
}
Alternatively one can use this method too, I found it helpful.
double a = 1.99;
System.out.println(Math.floor(a) == Math.ceil(a));
You can use:
double x=4;
//To check if it is an integer.
return (int)x == x;

Categories