Why Is Java's Division Broken

Why is Java's division broken?

You are thinking like a PHP developer; PHP is dynamically typed language. This means that types are deduced at run-time, so a fraction cannot logically produce a whole number, thus a double (or float) is implied from the division operation.

Java, C, C++, C# and many other languages are strongly typed languages, so when an integer is divided by an integer you get an integer back, 100/50 gives me back 2, just like 100/45 gives me 2, because 100/45 is actually 2.2222..., truncate the decimal to get a whole number (integer division) and you get 2.

In a strongly typed language, if you want a result to be what you expect, you need to be explicit (or implicit), which is why having one of your parameters in your division operation be a double or float will result in floating point division (which gives back fractions).

So in Java, you could do one of the following to get a fractional number:

double result = 1.0 / 2;
double result = 1f / 2;
double result = (float)1 / 2;

Going from a loosely typed, dynamic language to a strongly typed, static language can be jarring, but there's no need to be scared. Just understand that you have to take extra care with validation beyond input, you also have to validate types.

Going from PHP to Java, you should know you can not do something like this:

$result = "2.0";
$result = "1.0" / $result;
echo $result * 3;

In PHP, this would produce the output 1.5 (since (1/2)*3 == 1.5), but in Java,

String result = "2.0";
result = "1.0" / result;
System.out.println(result * 1.5);

This will result in an error because you cannot divide a string (it's not a number).

Hope that can help.

Java Division error

Dividing two ints will get you an int, which is then implicitly converted to double. Cast one to a double before the divison:

double diff = (double)end / first;

Why does this simple division between 2 floats not work with java?

What Every Programmer Should Know About Floating-Point Arithmetic:

Q: Why don’t my numbers, like 0.1 + 0.2
add up to a nice round 0.3, and
instead I get a weird result like
0.30000000000000004?

A: Because internally, computers use a
format (binary floating-point) that
cannot accurately represent a number
like 0.1, 0.2 or 0.3 at all.

In-depth explanations at the linked-to site

BigDecimal.Divide gives incorrect result

You asked the divide() call for 13 digits of precision, and that is what it gave you.

You then convert that to double and notice that double cannot handle that precision.

BigDecimal d1 = new BigDecimal(String.valueOf(221500.0)).setScale(13, BigDecimal.ROUND_HALF_UP);
BigDecimal d2 = new BigDecimal(String.valueOf(12.0)).setScale(13, BigDecimal.ROUND_HALF_UP);
BigDecimal d3 = d1.divide(d2, 13, BigDecimal.ROUND_HALF_UP);
System.out.println("BigDecimal: " + d3);
System.out.println("as double : " + d3.doubleValue());

OUTPUT

BigDecimal: 18458.3333333333333
as double : 18458.333333333332

If you're going to throw away the extra precision gained by using BigDecimal, why not just do the math in double?


On a different note:

Don't do new BigDecimal(String.valueOf(doubleValue)).

Use BigDecimal.valueOf(doubleValue).

Setting the scale of d1 and d2 seems rather meaningless.

Unless explicitly needed, round as late as possible, if at all.

Why byte and short division results in int in Java?

The main reason is that machines usually have only add instructions for their native integer type (and floats). This is why for many languages the least used type in an arithmetic expression is int (usually the type that correspond in some way to the basic machine integer type).

For example, i386 spec says:

ADD performs an integer addition of the two operands (DEST and SRC).
The result of the addition is assigned to the first operand (DEST),
and the flags are set accordingly. When an immediate byte is added to
a word or doubleword operand, the immediate value is sign-extended to
the size of the word or doubleword operand.

This means that internally any byte value is extended to an integer (or similar). After all this is reasonable as the processor is 32/64 bits and then perform any arithmetic in these sizes. If it could be possible to make arithmetic in bytes this is generally not considered as useful.

The JVM specs says that (for addition) you have : iadd, ladd, fadd, dadd. This just reflect the fact that underlying machines usually behave such. Any other choice could have been possible, probably at the price of performance degradation.

Java division by zero doesnt throw an ArithmeticException - why?

Why can't you just check it yourself and throw an exception if that is what you want.

    try {
for (int i = 0; i < tab.length; i++) {
tab[i] = 1.0 / tab[i];

if (tab[i] == Double.POSITIVE_INFINITY ||
tab[i] == Double.NEGATIVE_INFINITY)
throw new ArithmeticException();
}
} catch (ArithmeticException ae) {
System.out.println("ArithmeticException occured!");
}

Divison operator ambiguity

Actually when you divide 9/5, it takes 9 as well as 5 as an integer and then, it evaluates the whole answer as integer only. Thus, 9/5 (which is actually 1.8) is then type casted from 1.8 to 1. The portion after decimal is truncated. Thus, in your first code, it multiplies everything with 1 so it gives wrong output.

Now you'll ask, I have type casted into double then why?

Well, the answer is that first it evaluates 9/5 which is equal to 1 (according to int division by computer). Then it type castes 1 into double i.e. 1.0. Thus, you can instead use 9.0/5.0. This will also give you correct answer.

Java different situation division

Try casting the float to an int and compare the results, if it's the same, then print the integer, otherwise, use the float:

public class Main {
public static void main(String[] args) {
int a = 6;
int b = 3;
getDivisionResult(a, b);
b = 4;
getDivisionResult(a, b);
}
private static void getDivisionResult(int a, int b) {
float div = (float) a / b;
int rounded = (int) div;
if(rounded == div)
System.out.println(rounded);
else
System.out.println(div);
}
}

Output:

2
1.5


Related Topics



Leave a reply



Submit