Weighted median in java - java

I'm trying to program a program to compute Weighted Median, but I have a small problem I couldn't solve.
to find the Weighted Median, you have to divide each weight by the sum then compare it with 0.5 if greater means the Weighted Median found then return the corresponding x value.
here an example:
x = [3,4,6,10]
w = [1,2,3,5]
1/11 > 1/2 ? no
1/11+ 2/11 > 1/2 ? no
1/11+ 2/11 + 3/11 > 1/2 ? yes
then return the 6 as it's the corresponding for 3
here's my attempt:
public static void main(String[] args) {
int[] x = new int[] {3,4,6,10};
int[] w = new int[] {1,2,3,5};
int sum = Arrays.stream(w).sum();//11
if ((w[0]/sum)>0.5){
System.out.print("The weighted meadin is " + x[0]);
}
else if ((w[0]/sum)+(w[1]/sum)>0.5){
System.out.print("The weighted meadin is " + x[1]);
}
else if ((w[0]/sum)+(w[1]/sum)+(w[2]/sum)>0.5){
System.out.print("The weighted meadin is " + x[2]);
}
else if ((w[0]/sum)+(w[1]/sum)+(w[2]/sum)+(w[3]/sum)>0.5){
System.out.print("The weighted meadin is " + x[3]);
}
else{
System.out.print("The weighted meadin not found");
}
}
this always returns last else statement.

The elements in the w array and the sum variable are all ints, so when performing a / operation you're in fact performing integer division - i.e., you're keeping only the "whole" part of the division, which is always 0 in this case.
Defining one of the operands as a double will make Java use floating point division, and solve your problem. E.g.:
double sum = Arrays.stream(w).sum();

Each division operation you use is integer division, since both operands are integers.
Try making it a floating point division.
One way is to rewrite each w[0] / sum and the like into w[0] * 1.0 / sum, for example.
Another is to just declare the sum variable as double.

Related

Generate random float, both bounds inclusive

I need to generate random real numbers in the range [-0.5, 0.5], both bounds inclusive.
I found various ways to generate similar ranges, like
-0.5 + Math.random()
But the upper bound is always exclusive, I need it inclusive as well. 0.5 must be inside the range.
One way to achieve this would be to create random int from -500 to 500 and then divide it by 1000.
int max = 500;
int min = -500;
int randomInt = rand.nextInt((max - min) + 1) + min;
float randomNum = randomInt / 1000.00f;
System.out.println(randomNum);
You can change the precision by adding and removing zeros from the integer boundaries and the divisor. (eG: create integers from -5 to +5 and divide by 10 for less precision)
A disadvantage of that solution is that it does not use the maximum precision provided by float/double data types.
I haven't seen any answer that uses bit-fiddling inside the IEEE-754 Double representation, so here's one.
Based on the observation that a rollover to a next binary exponent is the same as adding 1 to the binary representation (actually this is by design):
Double.longBitsToDouble(0x3ff0000000000000L) // 1.0
Double.longBitsToDouble(0x3ffFFFFFFFFFFFFFL) // 1.9999999999999998
Double.longBitsToDouble(0x4000000000000000L) // 2.0
I came up with this:
long l = ThreadLocalRandom.current().nextLong(0x0010000000000001L);
double r = Double.longBitsToDouble(l + 0x3ff0000000000000L) - 1.5;
This technique works only with ranges that span a binary number (1, 2, 4, 8, 0.5, 0.25, etc) but for those ranges this approach is possibly the most efficient and accurate. This example is tuned for a span of 1. For ranges that do not span a binary range, you can still use this technique to get a different span. Apply the technique to get a number in the range [0, 1] and scale the result to the desired span. This has negligible accuracy loss, and the resulting accuracy is actually identical to that of Random.nextDouble(double, double).
For other spans, execute this code to find the offset:
double span = 0.125;
if (!(span > 0.0) || (Double.doubleToLongBits(span) & 0x000FFFFFFFFFFFFFL) != 0)
throw new IllegalArgumentException("'span' is not a binary number: " + span);
if (span * 2 >= Double.MAX_VALUE)
throw new IllegalArgumentException("'span' is too large: " + span);
System.out.println("Offset: 0x" + Long.toHexString(Double.doubleToLongBits(span)));
When you plug this offset into the second line of the actual code, you get a value in the range [span, 2*span]. Subtract the span to get a value starting at 0.
You can adjust the upper bound by the minimal value (epsilon) larger than the maxium value you expect. To find the epsilon, start with any positive value and make it as small as it can get:
double min = -0.5;
double max = 0.5;
double epsilon = 1;
while (max + epsilon / 2 > max) {
epsilon /= 2;
}
Random random = ThreadLocalRandom.current();
DoubleStream randomDoubles = random.doubles(min, max + epsilon);
Edit: alternative suggested by #DodgyCodeException (results in same epsilon as above):
double min = -0.5;
double max = 0.5;
double maxPlusEpsilon = Double.longBitsToDouble(Double.doubleToLongBits(max) + 1L)
Random random = ThreadLocalRandom.current();
DoubleStream randomDoubles = random.doubles(min, maxPlusEpsilon);
Given HOW GOD SPIDERS answer, here is a ready to use function :
public static double randomFloat(double minInclusive, double maxInclusive, double precision) {
int max = (int)(maxInclusive/precision);
int min = (int)(minInclusive/precision);
Random rand = new Random();
int randomInt = rand.nextInt((max - min) + 1) + min;
double randomNum = randomInt * precision;
return randomNum;
}
then
System.out.print(randomFloat(-0.5, 0.5, 0.01));
#OH GOD SPIDERS' answer gave me an idea to develop it into an answer that gives greater precision. nextLong() gives a value between MIN_VALUE and MAX_VALUE with more than adequate precision when cast to double.
double randomNum = (rand.nextLong() / 2.0) / Long.MAX_VALUE;
Proof that bounds are inclusive:
assert (Long.MIN_VALUE/2.0)/Long.MAX_VALUE == -0.5;
assert (Long.MAX_VALUE/2.0)/Long.MAX_VALUE == 0.5;
Random.nextDouble gives a value in the range of [0, 1]. So to map that to a range of [-0.5, 0.5] you just need to subtract by 0.5.
You can use this code to get the desired output
double value = r.nextDouble() - 0.5;

How can I use a formula in a for loop in java

I am a beginner java programmer, studying off basic youtube videos and overflow forums, and i came across a question on an textbook sheet that asked me to use a for loop program and print this table out as well as fill in each blank
Number Square Cube (n+1)/(2n-18)
______________________________________
1 # # #
2 # # #
3 # # #
4 # # #
5 # # #
I thought I should try it out to test myself. I came up with the following program that works perfectly for the Number, Square and Cube part of the table, but I don't understand how to generate the numbers using the given formula. The formula I initialized as a variable (double) doesn't print the actual results, and I honestly don't have a clue as to what to do. I'd rather a simple explanation than a complex one and simple changes to the code rather than complex. As I said I am a beginner, and many different methods may go right over my head. Thank you so much in advance (also an extra task asks that I print out the sums of each column. I don't know how to do that at all, and would like an explanation if possible, but wouldn't mind if I don't receive one)
int number;
int maxValue;
Scanner keyboard = new Scanner(System.in);
System.out.println("how many numbers do you want the max value to be");
maxValue = keyboard.nextInt();
System.out.println("Number\tSquare\tCube (n+1)/(2n-18)");
System.out.println("--------------------------------");
for (number = 1; number <= maxValue; number++) {
double formula = (number + 1) / (number * 2);
System.out.println(
number + "\t\t\t" + number * number + "\t\t\t" +
number * number * number + "\t\t\t" + formula);
}
Your formula should be:
double formula = (double)(number + 1) / (number * 2 - 18);
Two issues:
missing -18
the / is doing an integer division unless you cast at least one operand into a double
Oh! one more thing: when number==9, there is a division by zero. A double division gives you "Infinity" whereas an integer division throws an exception.
Your formula does not match the textbook. Try this:
System.out.println("Number\tSquare\tCube (n+1)/(2n-18)");
System.out.println("--------------------------------");
for (int number=1; number <= maxValue; number++) {
double square = Math.pow(number, 2);
double cube = Math.pow(number, 3);
double formula = (number + 1) / (number * 2 - 18);
System.out.println(number + "\t\t\t" + square + "\t\t\t" + cube + "\t\t\t" + formula);
}
Note: As pointed out by #MauricePerry an input of 9 would cause a divide by zero. Rather than try to catch this unchecked exception, I think you should control your input values so that this does not happen.
Your formula is not correct and you are missing few \t.
int number;
int maxValue;
Scanner keyboard = new Scanner(System.in);
System.out.println("how many numbers do you want the max value to be");
maxValue = keyboard.nextInt();
System.out.println("Number\t\tSquare\t\tCube \t\t(n+1)/(2n-18)");
System.out.println("-------------------------------------------------------");
for (number = 1; number <= maxValue; number++) {
double formula = (number + 1) / (number * 2 - 18);
System.out
.println(number + "\t\t" + number * number + "\t\t" + number * number * number + "\t\t" + formula);
}
I'm not sure which outputs are you getting, but it seems to me you're using integer division when trying to get the result of (n+1)/(2n-18).
Try using:
double decimalNumber = (double) number;
double formula = (decimalNumber + 1) / (decimalNumber * 2 - 18);

Syntax error on tokens in string text

I keep getting "syntax error on tokens please delete these tokens" on pretty much all of my System.out.println text after the first instance of System.out.println. I don't know what this means or how to fix it? I'm a very new beginning so there might be multiple mistakes in this code. I'm also getting "Syntax error on token ""doubled is"", invalid AssignmentOperator" and """squared is"", invalid AssignmentOperator" errors as well. This is an assignment for a class with the end result supposed to be
the opposite of n is y
n doubled is y
one-half of n is y
n squared is y
the reciprocal of n is y
one-tenth of n is y and y squared is z
n minus the last digit of n is y
the sum of n and n+1 and n+2 is y
Thank you!
import java.util.Scanner;
public class Arithmetic {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter an integer: ");
int n = scanner.nextInt();
int opposite = n*-1;
System.out.println("The opposite of" n "is" opposite);
int twoTimes = n*2;
System.out.println(n "doubled is" twoTimes);
int half = n/2;
System.out.println("half of "n "is" half);
int square= n*n;
System.out.println(n "squared is" square);
int reciprocal= 1/n;
System.out.println("the reciprocal of" n "is" reciprocal);
double fraction = n*.10;
double fractionTwo = fraction*fraction;
System.out.println("one-tenth of" n "is" fraction "and" fraction "squared is" fractionTwo);
// int lastDigit =
// System.out.println();
int sum= n+1;
int sumTwo= n+2;
int sumTotal= sum + sumTwo;
System.out.println("the sum of" n "and" sum "and" sumTwo "is" sumTotal);
}
}
**also if anybody would like to help me figure out the "n+1"/"n+2" formula and how to format that in code that would be appreciated!
There's a few mistakes with this code.
You're not concatenating correctly on any of your print to consoles.
System.out.println("The opposite of" n "is" opposite);
should be:
System.out.println("The opposite of" + n + "is" + opposite);
When we want to combine Strings we use the + sign.
int reciprocal= 1/n; will not work;
it should be double reciprocal= 1.0/n; assuming that n is an int.
"n+1"/"n+2" would simply be: double result = (n + 1.0) / (n + 2.0); assuming that n is an int.
That's not how you concatenate (link) two strings!
This code, and other similar ones,
System.out.println(n "doubled is" twoTimes);
are wrong.
I think you want to link n, "doubled is" and twoTimes together, right?
Right now you are linking them with spaces. But space characters in Java doesn't concatenate strings. So that's why the compiler complained.
In Java, + is both used to do addition and concatenation of strings! So you should change the above to:
System.out.println(n + "doubled is" + twoTimes);
But wait! Where have your spaces gone? This is because + doesn't automatically adds a space for you, you need to add it yourself.
System.out.println(n + " doubled is " + twoTimes);
Alternatively, you can use String.format to format your string. This
/* Explanation: n will be "inserted" to the first %d and twoTimes will
be inserted to the second %d. And %d basically means "express the thing in
decimal"*/
String.format("%d doubled is %d", n, twoTimes)
is the same as
n + " doubled is " + twoTimes
Regarding your formula question:
In Java, there are two different number types, int and double. (There are actually a lot more, but they're irrelevant) int and double do different things when they are divided. And they have different literals.
5 is an int literal, 5.0 is a double literal. See? Numbers without decimal places are ints and those with decimal places are called doubles.
So what's wrong with your formula? Let's first take a look at what the is the result of dividing int and double
int / int: 1 / 5 = 0
int / double: 1 / 5.0 = 0.2
double / int: 1.0 / 5 = 0.2
double / double: 1.0 / 5.0 = 0.2
int / 0: 1 / 0 = Exception!
double / 0: 1.0 / 0 = NaN
In your code:
int reciprocal= 1/n;
and other similar lines, you are doing division of int. So that's why the above code doesn't work. What you should do is change one of the numbers to a double! And also change the type to double.
double reciprocal = 1.0 / n;
------ ---
changes here as well!

Am i properly handling this float variable?

I want to make sure that initializationg of the float variable resultd is correct. Since it is where the error lies.
static void caculateValues() {
int a, b;
int resulta, results, resultm;
float resultd;
Scanner sc = new Scanner(System.in);
System.out.print("Enter a:");
a = sc.nextInt();
System.out.print("Enter b:");
b = sc.nextInt();
{
//This is the only part I edited//
resulta= a+b;
results=a-b;
resultm= a * b;
resultd= a / b;
//This is where I stopped editing//
}
System.out.println("The result of adding is " + resulta);
System.out.println("The result of subtracting is " + results);
System.out.println("The result of multiplying is " + resultm);
System.out.println("The result of dividing is " + resultd);
}
They claim my output should looks something like this:
(a = -50) (b = -20)
The result of adding is -70
The result of subtracting is -30
The result of multiplying is 1000
The result of dividing is 2.5
But supposedly my input shows:
The result of adding is -70
The result of subtracting is -30
The result of multiplying is 1000
The result of dividing is 2.0
Even if resultd is a float, you are still dividing two ints:
a / b
In Java, division of 2 ints must be an int. That is why 2.0 is showing up. -50 / -20 is 2, not 2.5 in Java. Only after the 2 is generated is it promoted to a float upon assignment to resultd.
Cast one of the variables to a float to force floating-point math from the start.
resultd = (float) a / b;
You could just as easily make resultd a double and cast a to a double instead.

Numerical specification in Java

Suppose in jdk 8 specification, and x1, x2 and y1, y2 are int variable, I want to know if following situations could happen:
mathematically x1/y1 != x2/y2 but in Java x1/(double)y1 == x2/(double)y2
mathematically x1/y1 == x2/y2 but in Java x1/(double)y1 != x2/(double)y2
Assuming mathematically 0/0 != 0/0 and Inf == Inf and +0 == -0
Ideally, you should specify a number system rather than the vague "mathematically". There are a lot of systems in mathematics that define division. I would have assumed you meant real number arithmetic, but it has a single zero and you seem to be permitting division by zero, which real number arithmetic does not define. I am going to assume you mean real number arithmetic for divisions not involving zero, extended in a way compatible with Java double arithmetic for divisions that do have a zero operand.
The first case can happen:
x1 = Integer.MAX_VALUE
y1 = Integer.MAX_VALUE-1
x2 = Integer.MAX_VALUE-1
y2 = Integer.MAX_VALUE-2
Both double divisions get the same answer: 1.0000000004656613
Clearly, the two divisions have different exact answers. The 40 decimal place BigDecimal results are:
1.0000000004656612877414201272105985574523
1.0000000004656612879582605622125704244886
Here is a demonstration program:
import java.math.BigDecimal;
public class Test {
public static void main(String[] args) {
double baseDouble = Integer.MAX_VALUE;
double minus1Double = Integer.MAX_VALUE - 1;
double minus2Double = Integer.MAX_VALUE - 2;
BigDecimal baseBD = new BigDecimal(Integer.MAX_VALUE);
BigDecimal minus1BD = new BigDecimal(Integer.MAX_VALUE - 1);
BigDecimal minus2BD = new BigDecimal(Integer.MAX_VALUE - 2);
System.out.println("base " + baseDouble + " " + baseBD);
System.out.println("minus1 " + minus1Double + " " + minus1BD);
System.out.println("minus2 " + minus2Double + " " + minus2BD);
System.out.println("Double base/minus1 " + baseDouble / minus1Double);
System.out.println("Double minus1/minus2 " + minus1Double / minus2Double);
System.out.println("BigDecimal base/minus1 "
+ baseBD.divide(minus1BD, 40, BigDecimal.ROUND_HALF_EVEN));
System.out.println("BigDecimal minus1/minus2 "
+ minus1BD.divide(minus2BD, 40, BigDecimal.ROUND_HALF_EVEN));
}
}
The output is:
base 2.147483647E9 2147483647
minus1 2.147483646E9 2147483646
minus2 2.147483645E9 2147483645
Double base/minus1 1.0000000004656613
Double minus1/minus2 1.0000000004656613
BigDecimal base/minus1 1.0000000004656612877414201272105985574523
BigDecimal minus1/minus2 1.0000000004656612879582605622125704244886
It is easy to see that the second case is impossible for divisions that do not have a zero operand.
Every int is exactly convertible to double, so the exact quotient of the doubles matches the exact quotient of the original values. For the definition of division, see the Java Language Specification, 15.17.2 Division Operator /. The process for dividing a pair of finite numbers neither of which is zero is equivalent to mapping the exact quotient into either the double value set or the double-extended-exponent value set.
Exponent overflow and underflow in double are impossible for the int range, so the two value sets will give the same answer. The rounding rules are independent of the calculation that led to the result being rounded, so two divisions of int-valued doubles that have the same exact quotient have the same rounded result.

Categories

Resources