Why is Java's division broken?

被刻印的时光 ゝ 提交于 2020-02-09 01:56:06

问题


I am an experienced php developer just starting to learn Java. I am following some Lynda courses at the moment and I'm still really early stages. I'm writing sample programs that ask for user input and do simple calculation and stuff.

Yesterday I came across this situation:

double result = 1 / 2;

With my caveman brain I would think result == 0.5, but no, not in Java. Apparantly 1 / 2 == 0.0. Yes, I know that if I change one of the operands to a double the result would also be a double.

This scares me actually. I can't help but think that this is very broken. It is very naive to think that an integer division results in an integer. I think it is even rarely the case.

But, as Java is very widely used and searching for 'why is java's division broken?' doesn't yield any results, I am probably wrong.

My questions are:

  1. Why does division behave like this?
  2. Where else can I expect to find such magic/voodoo/unexpected behaviour?

回答1:


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.




回答2:


Java is a strongly typed language so you should be aware of the types of the values in expressions. If not...

1 is an int (as 2), so 1/2 is the integer division of 1 and 2, so the result is 0 as an int. Then the result is converted to a corresponding double value, so 0.0.

Integer division is different than float division, as in math (natural numbers division is different than real numbers division).




回答3:


I'm by no means a professional on this, but I think it's because of how the operators are defined to do integer arithmetic. Java uses integer division in order to compute the result because it sees that both are integers. It takes as inputs to this "division" method two ints, and the division operator is overloaded, and performs this integer division. If this were not the case, then Java would have to perform a cast in the overloaded method to a double each time, which is in essence useless if you can perform the cast prior anyways.




回答4:


If you try it with c++, you will see the result is the same. The reason is that before assigning the value to the variable, you should calculate it. The numbers you typed (1 and 2) are integers, so their memory allocation should be as integers. Then, the division should done according to integers. After that it will cast it to double, which gives 0.0.




回答5:


Why does division behave like this?

Because the language specification defines it that way.

Where else can I expect to find such magic/voodoo/unexpected behaviour?

Since you're basically calling "magic/voodoo" something which is perfectly defined in the language specification, the answer is "everywhere".

So the question is actually why there was this design decision in Java. From my point of view, int division resulting in int is a perfectly sound design decision for a strongly typed language. Pure int arithmetic is used very often, so would an int division result in float or double, you'd need a lot of rounding which would not be good.



来源:https://stackoverflow.com/questions/41034020/why-is-javas-division-broken

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!