Numerical specification in Java - 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.

Related

Weighted median in 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.

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!

Can val be used as variable in Java?

Is the program legal or not?
I am trying to correct out a statement that will print the value of 3 divided by 2.
I know this isn't correct.
System.out.print("The result is" + 3 / 2 + ".")
This is my answer.
System.out.print("The result is" + val + ".")
double val = 3 / 2
Is my answer correct or no? If not, how would I call upon the number?
You can do the following
double val = 3.0 / 2;
System.out.print("The result is" + val + ".");
the value val must be declared before it is printed. Also you need to make one of the number of type double so when the division is done, the answer is a double also. Else you lose precision.
the following is also valid:
double val = 3 / 2.0;
System.out.print("The result is" + val + ".");
if you do double val = 3 / 2; then 3/2 division is made with two integers which also give another integer. So 3/2 should give 1.5 but since we are only diving integers, it will omit the .5 and only give 1. Then 1 is casted as a double and becomes 1.0.
What you have is mostly correct:
float val1 = 3;
float val2 = 2;
float val= val1/val2;
System.out.println("The result is " + val + ".");
Remember your semicolons.
Also... You are correct to use a double (or float). Because otherwise your answer will be truncated.
EDIT:
Actually... I come to find that trying to do the operation in one shot still truncates the answer. It isn't correct unless both the values are set as floats. Then, run the math.
Here is proof: online java compiler
You need to declare first the variables. And if you want fraction numbers you need to do that with them. Need " ; " at the end of every statement. If you try it out in eclipse it will sign error to you when you don't write it where it need to be.
float num1 = 3;
float num2 = 2;
float val = num1 / num2;
System.out.print("The result is" + val + ".");
// Another way:
double num1 = 3;
double num2 = 2;
double val = num1 / num2;
System.out.print("The result is" + val + ".");
This should work:
double val = 3.0 / 2;
System.out.print("The result is" + val + ".");
Edit:
This is a case of integer division. When division is performed between two integers (here 3 and 2), the output is an integer and the fractional part gets trimmed off. So,3/2 will yield 1 which since you assign to a double variable, becomes 1.0.
When I do 3.0/2, 3.0 is a double value. The output here is a double value too i.e. 1.5; the fractional part is retained. Hence, my solution works.

Unexpected behavior of double primitive type data

I want to understand how the Java double type will store its value in memory in Java.
When I run the following code I get unexpected output:
public static void main(String[] args) {
float a = 1.5f;
float b= 0.5f;
double c= 1.5;
double d = 0.5;
float a1 = 1.4f;
float b1= 0.5f;
double c1= 1.4;
double d1 = 0.5;
System.out.println(" a- b is " + (a-b));
System.out.println(" c- d is " + (c-d));
System.out.println("a1-b1 is " + (a1-b1));
System.out.println("c1-d1 is " + (c1-d1));
}
Output:
a- b is 1.0
c- d is 1.0
a1-b1 is 0.9
c1-d1 is 0.8999999999999999
Why is c1-d1 not equal to 0.9?
I also tried other different values but some time it return expected result and some time not.
While you might have heard about rounding errors, you might be wondering why you have a rounding error here.
float a1 = 1.4f;
float b1 = 0.5f;
double c1 = 1.4;
double d1 = 0.5;
System.out.println(new BigDecimal(a1) + " - " + new BigDecimal(b1) + " is " +
new BigDecimal(a1).subtract(new BigDecimal(b1)) + " or as a float is " + (a1 - b1));
System.out.println(new BigDecimal(c1) + " - " + new BigDecimal(d1) + " is " +
new BigDecimal(c1).subtract(new BigDecimal(d1)) + " or as a double is " + (c1 - d1));
prints
1.39999997615814208984375 - 0.5 is 0.89999997615814208984375 or as a float is 0.9
1.399999999999999911182158029987476766109466552734375 - 0.5 is
0.899999999999999911182158029987476766109466552734375
or as a double is 0.8999999999999999
As you can see, neither float nor double can represent these values exactly, and when the float or double is printed, some rounding occurs to hide this from you. In this case of float, the rounding to 7 decimal places yields the number you expected. In the case of double which has 16 digits of precision, the rounding error is visible.
As #Eric Postpischil, notes whether the float or double operation has a rounding error depends entirely on the values used. In this situation, it was the float which appeared to be more accurate even through the represented value was further from 0.9 than the double value.
In short: if you are going to use float or double you should use a sensible rounding strategy. If you can't do this, use BigDecimal.
System.out.printf("a1 - b1 is %.2f%n", (a1 - b1));
System.out.printf("c1 - d1 is %.2f%n", (c1 - d1));
prints
a1 - b1 is 0.90
c1 - d1 is 0.90
When you print a float or double, it assumes that the nearest short decimal value is the one you really want. i.e. within 0.5 ulp.
E.g.
double d = 1.4 - 0.5;
float f = d;
System.out.println("d = " + d + " f = " + f);
prints
d = 0.8999999999999999 f = 0.9
Java documentation for println refers (through several links) to the documentation for toString. The documentation for toString says that the number of digits printed for float or double is the number needed to uniquely distinguish the value from adjacent representable values in the same type.
When “1.4f” is converted to float, the result is 1.39999997615814208984375 (in hexadecimal floating point, 0x1.666666p+0). When .5 is subtracted, the result is 0.89999997615814208984375 (0x1.ccccccp-1). As it happens, this float is also the float that is closest to .9. So, when it is printed, “.9” is printed.
When “1.4” is converted to double, the result is 1.399999999999999911182158029987476766109466552734375 (0x1.6666666666666p+0). When .5 is subtracted, the result is 0.899999999999999911182158029987476766109466552734375 (0x1.cccccccccccccp-1). This is not the double that is closest to .9, as 0.90000000000000002220446049250313080847263336181640625 (0x1.ccccccccccccdp-1) is closer. Therefore, when it is printed, the Java specification requires that the value be printed more finely, distinguishing it from .9. The result, “0.8999999999999999”, accurately represents the actual value.

Why is this true?

This is IEEE 754 standard question. I don't completely understand the mechanics behind it.
public class Gray {
public static void main(String[] args){
System.out.println( (float) (2000000000) == (float) (2000000000 + 50));
}
}
Because a float can only hold about 7 to 8 significant digits. That is, it doesn't have enough bits to represent the number 2000000050 exactly, so it gets rounded to 2000000000.
Specifically speaking, a float consists of three parts:
the sign bit (1 bit)
the exponent (8 bits)
the significand (24 bits, but only 23 bits are stored since the MSB of the significand is always 1)
You can think of floating point as the computer's way doing scientific notation, but in binary.
The precision is equal to log(2 ^ number of significand bits). That means a float can hold log(2 ^ 24) = 7.225 significant digits.
The number 2,000,000,050 has 9 significant digits. The calculation above tells us that a 24-bit significand can't hold that many significant digits. The reason why 2,000,000,000 works because there's only 1 significant digit, so it fits in the significand.
To solve the problem, you would use a double since it has a 52-bit significand, which is more than enough to represent every possible 32-bit number.
Plainly said - 50 is a rounding error when a float has a value of two-billion.
You might find this trick to find the next representable value interesting.
float f = 2000000000;
int binaryValue = Float.floatToRawIntBits(f);
int nextBinaryValue = binaryValue+1;
float nextFloat = Float.intBitsToFloat(nextBinaryValue);
System.out.printf("The next float value after %.0f is %.0f%n", f, nextFloat);
double d = 2000000000;
long binaryValue2 = Double.doubleToRawLongBits(d);
long nextBinaryValue2 = binaryValue2+1;
double nextDouble = Double.longBitsToDouble(nextBinaryValue2);
System.out.printf("The next double value after %.7f is %.7f%n", d, nextDouble);
prints
The next float value after 2000000000 is 2000000128
The next double value after 2000000000.0000000 is 2000000000.0000002
It might help you understand the situation if you consider a program (C++) as below. It displays the groups of successive integers that get rounded to the same float value:
#include <iostream>
#include <iomanip>
int main()
{
float prev = 0;
int count = 0;
double from;
for (double to = 2000000000 - 150; count < 10; to += 1.0)
{
float now = to;
if (now != prev)
{
if (count)
std::cout << std::setprecision(20) << from << ".." << to - 1 << " ==> " << prev << '\n';
prev = now;
from = to;
++count;
}
}
}
Output:
1999999850..1999999935 ==> 1999999872
1999999936..2000000064 ==> 2000000000
2000000065..2000000191 ==> 2000000128
2000000192..2000000320 ==> 2000000256
2000000321..2000000447 ==> 2000000384
2000000448..2000000576 ==> 2000000512
2000000577..2000000703 ==> 2000000640
2000000704..2000000832 ==> 2000000768
2000000833..2000000959 ==> 2000000896
This indicates that floating point is only precise enough to represent all integers from 1999999850 to 1999999935, wrongly recording their value as 1999999872. So on for other values. This is the tangible consequence of the limited storage space mentioned above.

Categories

Resources