How to calculate integer expression in Java - java

Suppose, I need to calculate 3 * (2 / 3) = 2 but 3 * (2 / 3) = 0 in integer arithmetic. So, it looks like I should use floating-point arithmetic 3 * (2.0 / 3) = 2.0 and cast the floating point result to int.
Does it make sense? How would you avoid casting here?

In this particular example, you may be better off rearranging the expression as 3 * 2 / 3, or as 3 / 3 * 2. This way you'll get the exact result using integer math alone.
Using floating-point math is the more general solution, but you need to be aware of rounding issues. In general, you shouldn't expect that x * (y / x) would give you exactly y when x and y are floating-point numbers.
If you know that the result is an integer, or simply want to round it to the nearest integer, you could use Math.round():
Math.round(3 * (2f / 3))
Simply casting the result to int is not a good idea since floating-point numbers are inexact, and such a cast would simply truncate the number.

You can't avoid casting. You can either use integer division or you can use full division but then arguments and result will be in floating point.
You can try moving around the expression parts to bring out the integer division to the top level. In your case you could transform 3 * (2 / 3) to (3 * 2) / 3 which will result in 2 without any floating point operations.

* and / have the same precedence, so omitting the parentheses will provide you with a correct result of the example.
Casting (or truncating) is unavoidable otherwise.

Personally I would re-arrange the equation to be:
3 / 3 * 2 = 2
But not sure if thats what you need. You could try doing the calculation on float's and then use round() to round it up or down to the nearest integar.

This is because of the integer division. In these kinds of expressions you are better off using float, yes.
You can avoid the explicit casting only if you are using the compound operator. The compound operator does an automatic cast for you.
int a = 3;
a *= (2.0/3);
System.out.println(a);

What exactly is it you want to achieve? Using integer arithmetic the result depends on where you set you parentheses. (a/b) * (c/d) * (e/f) will, as you noticed yourself, in general result in something different than (a*c*d) / (b*d*f), even though mathematically both expressions are equal. Nontheless both expressions may be correct depending on the task you want to solve. I do miss a clear statement of this.
If you are looking for the integer closest to the mathematically correct value just calculate nominator and denominator seperately and then perform the division. This way intermediate errors do not occur. If not you need to reformulate your question.

Related

Can anyone tell me why this is evaluating to 0?

Working on a Java class, its making me crazy because this expression is evaluating to zero, I need it to evaluate to a double, then round it down to the nearest int. So what Im trying to get is for days to be a whole number of days, yet when I run it through java it evaluates to 0. When I run it through my calculator it evaluates to the correct value. I would love a fix and an explanation to why this what I already have isn't working.
public int getEventDays(){
//variables
double daysCalc;
int days;
//logic
if (getStatus().equals("filling")){
//this is indented less to fit everything on one line, its not this way in
//the fractions are for unit conversion
daysCalc= Math.floor(((capacity-storage)/(inflow-outflow))*(43560)*(1/3600)*(1/24));
days = (int)daysCalc;
}
else if (getStatus().equals("emptying")){
//this is indented less to fit everything
//the fractions are for unit conversion
daysCalc=Math.floor(((storage-0)/(outflow-inflow))*(43560)*(1/3600)*(1/24));
days = (int)daysCalc;
}
else{
days = -1;
}
return days;
}
Change your code to this :
daysCalc = Math.floor(((storage-0)/(outflow-inflow))*(43560)*(1.0/3600)*(1.0/24));
Explanation:
The right hand expression is returning an integer value. In your case, 1/3600 is rounded to 0, similar to the case of 1/24.
Now by using 1.0 instead of 1, it is giving the unrounded float value of 1/3600.
Your problem is connected with the order of operations within your expression. The parentheses around 1/3600 and 1/24 cause these expressions to be evaluated first - and since each of these divisions has an expression of integer type on either side of the division, it's treated as an integer division. In other words, 1/3600 and 1/24 are both evaluated as integers, to give a result of zero. This means that your arithmetic includes a couple of multiplications by zero, which is why your result is zero.
The simplest fix is to understand that multiplying by the reciprocal of some number is the same as dividing by that number. In other words, you could simplify the calculation to
daysCalc = Math.floor( storage / ( outflow - inflow ) * 43560 / 3600 / 24 );
which will give the correct result, provided storage, outflow and inflow are not all integers.
On the other hand, if storage, outflow and inflow are all integers, then you'll need to make sure that the first division is also not treated as an integer division. You could do this by writing
daysCalc = Math.floor((double) storage / ( outflow - inflow ) * 43560 / 3600 / 24 );
which forces the division to be done with floating point arithmetic; and thereafter, each one of the divisions is done in floating point.

Parentheses and order of operations

I have a function in java that returns an integer. I know what it is supposed to return so I know when it runs correctly or not. Anyway, there is this line of code at some point in a for loop:
If I write it like this
miuf = miuf_ant * nf_ant / nf - ((double) ((t - 1) * hist[t - 1]) / (double) nf);`
the result is fine.
If I write it like this
miuf = (miuf_ant * (nf_ant / nf) - ((double) ((t - 1) * hist[t - 1]) / (double) nf));
the result is way off.
nf_ant, nf and t are ints, the rest are doubles.
I have evaluated these 2 expressions in the debugger for a few iterations and the results differ by some 0.3 in general. Why does this happen and why is it that one works and the other doesn't?
If nf_ant and nf are ints, your problem is that the second version if performing integer division and not floating point division. You need to cast one of them first.
Let's compare the following two expressions:
miuf_ant * nf_ant / nf
miuf_ant * (nf_ant / nf)
The first one is equivalent to the following by the rules of Java:
(miuf_ant * nf_ant) / nf
What happens here is that the product is evaluated first, and because miuf_ant is double, the result is also a double. Afterwards, the same happends for the division.
In the "bad" (second) case though, because both division operators are ints, the result is also an int, losing precission on the operation by effectively truncating the result. This loss of precission is then carried to the product.
In the second case, nf_ant / nf will be computed in integer arithmetic as the parentheses mean it's evaluated on its own. This loss of the remainder is the cause of the difference.
In the first case it is premultiplied by miuf_ant which is a floating point type. Since * and / have the same precedence, all 3 arguments are promoted to floating point prior to computation.

Weird decimal calculation in Java, potentially a bug?

I have weird decimal calculation that really surprise me, I have two big decimal number, one is a normal proce and the other one is an offer price. Then I want to calculate discount percentage and ceil it to the nearest integer.
Here are the code:
BigDecimal listPrice = new BigDecimal(510000);
BigDecimal offerPrice = new BigDecimal(433500);
int itemDiscount = (int)Math.ceil(((listPrice.longValue() - offerPrice.longValue()) / (float) listPrice.longValue()) * 100);
I expect it would set 15 as value of itemDiscount, but surprisingly it has 16, wow. Then i print each calculation to show in which statement is the problem, so i put System.out.println for each statement as below :
System.out.println(listPrice.longValue() - offerPrice.longValue()); //==> show 76500
System.out.println((listPrice.longValue() - offerPrice.longValue()) / (float) listPrice.longValue()); // ==> 0.15
System.out.println((listPrice.longValue() - offerPrice.longValue()) * 100 / (float) listPrice.longValue()); // ==> 15.000001
the problem is in above statement, istead of returning 15.0, it return 15.000001. And when i ceil it, it will of course return 16 instead of 15.
What is the explanation if this case? is this the way it is or it is a bug?
What is the explanation if this case? is this the way it is or it is a bug?
It is the way it is. It is not a bug.
You are doing the calculation using floating point types (float) and floating point arithmetic is imprecise.
I'm not sure what the best fix is here. Maybe doing the computation using BigDecimal arithmetic methods would give a better result, but it is by no means guaranteed that you won't get similar problems in this calculation with different inputs ...
However, I suspect that the real problem is that you should not be using ceil in that calculation. Even BigDecimal will give you rounding errors; e.g. if your computation involves dividing by 3, the intermediate result cannot be precisely represented using a base-10 representation.
The correct way to do calculations using Real numbers is to properly take account of the error bars in the calculation.
Try using the divide method directly from the BigDecimal class. If you are casting to a float then you are not using the benefit of BigDecimal .
http://www.roseindia.net/java/java-bigdecimal/bigDecimal-divide-int.shtml

Logically questionable?

double x = 1;
double y = 3 * (1.0 / 3);
x == y
In a powerpoint I am studying, it said the statement is logically questionable. I cannot find out why it is thus, I mean you use == for primitives correct, or is it Logically questionable because doubles are not stored exactly or am I missing something obvious? Thanks
I think you've got it: since the data types are doubles, rather than int or Integer, the resulting x and y may not be precisely equal.
It is logically questionable because the compare statement at the end would evaluate to false. Doubles are stored as a series of powers of two. So values like 1/2 and 1/4 and 1/8 could actually be expressed in floating point formats exactly, but not 1/3. It will be approximated to 1/4 + 1/64 + ... there is now way it could exactly be apprroximate 1/3
Correct way to compare the floats is like this:
Math.double.abs ( x - y ) > tol
where tol is set to something sufficiently small, depending on your application. For example most graphics applications work well with tol = 0.00001
Because 1.0 / 3 is 0.3333..., up to the capacity of a double. 3 * 0.3333... is 0.9999..., up to the capacity of a double.
So we have the question 1 == 0.9999..., which I guess you could call "logically questionable".
It's because of roundoff error. The problem is analogous to the precision problems you have have with decimals when dealing with numbers that cannot be precisely expressed in the format you are using.
For example, with six digits of decimal precision, the best you can do for 1/3 is .333333. But:
1/3 + 1/3 + 1/3 -> .33333 + .333333 + .33333 = .999999 != 1.000000
Ouch. For 2/3, you can use either .666666 or .666667 but either way, you have problems.
If 2/3 -> .666666 then:
2/3 + 1/3 -> .333333 + .666666 != 1.000000
Ouch.
And if 2/3. -> .666667 then:
1/3 * 2 - 2/3 -> .333333 * 2.00000 - .666667 = .666666 - .666667 != 0
Ouch.
It's analogous with doubles. This paper is considered the authoritative work on the subject. In simple terms -- never compare floating point numbers for equality unless you know exactly what you're doing.
Logically questionable because doubles are not stored exactly
More or less.
As a general rule, a double cannot represent the precise value of a Real number. The value 1/3 is an example.
Some numbers can be represented precisely as double values. 1.0 and 3.0 are examples. However, the division operator produces a number (in this case) that cannot be represented.
In general, any code that uses == to compare double or float values is questionable ... in the sense that you need to analyse each case carefully to know whether the use of == is correct. (And the analysis is not intuitive for people who were taught at a very early age to do arithmetic in base 10!)
From the software engineering standpoint, the fact that you need to do a case-by-case analysis of == usage makes it questionable practice. Good software engineering is (in part) about eliminating mistakes and sources of mistakes.

Is "long x = 1/2" equal to 1 or 0, and why? [duplicate]

This question already has answers here:
Integer division: How do you produce a double?
(11 answers)
Closed 7 years ago.
if I have something like:
long x = 1/2;
shouldn't this be rounded up to 1? When I print it on the screen it say 0.
It's doing integer division, which truncates everything to the right of the decimal point.
Integer division has its roots in number theory. When you do 1/2 you are asking how many times does 2 equal 1? The answer is never, so the equation becomes 0*2 + 1 = 1, where 0 is the quotient (what you get from 1/2) and 1 is the remainder (what you get from 1%2).
It is right to point out that % is not a true modulus in the mathematical sense but always a remainder from division. There is a difference when you are dealing with negative integers.
Hope that helps.
What this expression is doing is it first declares the existence of a long called x, and then assigning it the value of the right hand side expression. The right hand side expression is 1/2, and since 1 and 2 are both integers this is interpreted as integer division. With integer division the result is always an Integer, so something along the lines of 5/3 will return 1, as only one three fits in a five. So with 1/2, how many 2s can fit into 1? 0.
This can in some languages result in some interesting outputs if you write something like
double x = 1/2. You might expect 0.5 in this case, but it will often evaluate the integer value on the right first before assigning and converting the result into a double, giving the value 0.0
It is important to note that when doing this kind of type conversion, it will never round the result. So if you do the opposite:
long x = (long)(1.0/2.0);
then while (1.0/2.0) will evaluate to 0.5, the (long) cast will force this to be truncated to 0. Even if I had long x = (long)(0.9), the result will still be 0. It simply truncates after the decimal point.
It can't round because it's never in a state to be rounded
The expression "1/2" is never 0.5 before assign to long
Now, long x = 1.0/2.0 because the expression on the right before assign is valid for rounding. Unless you get 0.499999999999997...
this question was answered before on this site, you are doing an integer division, if you want to get the 0.5 use:
double x = (double)1/2;
and you will get the value of 0.5 .
There are lots of different rounding conventions, the most common being rounding towards +inf, rounding towards -inf and rounding towards zero. Lots of people assume there's one right way, but they all have different ideas about what that one way should be ;-)
There is no intermediate non-integer result for integer division, but of course the division is done deterministically, and one particular rounding convention will always be followed for a particular platform and compiler.
With Visual C++ I get 5/2 = 2 and -5/2 = -2, rounding towards zero.
The rounding in C, C++ and Java is commonly called "truncation" - meaning drop off the unwanted bits. But this can be misleading. Using 4 bit 2s complement binary, doing what truncation implies gives...
5/2 = 0101/0010 = 0010.1 --> 0010 = 2
-5/2 = 1011/0010 = 1101.1 --> 1101 = -3
Which is rounding towards -infinity, which is what Python does (or at least what it did in Python 2.5).
Truncation would be the right word if we used a sign-magnitude representation, but twos complement has been the de-facto standard for decades.
In C and C++, I expect while it's normally called truncation, in reality this detail is undefined in the standards and left to the implementation - an excuse for allowing the compiler to use the simplest and fastest method for the platform (what the processors division instruction naturally does). It's only an issue if you have negative numbers though - I've yet to see any language or implementation that would give 5/2 = 3.
I don't know what the Java standard says. The Python manual specifies "floor" division, which is a common term for rounding to -infinity.
EDIT
An extra note - by definition, if a/b = c remainder d, then a = (b*c)+d. For this to hold, you have to choose a remainder to suite your rounding convention.
People tend to assume that remainders and modulos are the same, but WRT signed values, they can be different - depending on the rounding rules. Modulo values are by definition never negative, but remainders can be negative.
I suspect the Python round-towards-negative-infinity rule is intended to ensure that the single % operator is valid both as a remainder and as a modulo. In C and C++, what % means (remainder or modulo) is (yes, you guessed it) implementation defined.
Ada actually has two separate operators - mod and rem. With division required to round towards zero, so that mod and rem do give different results.

Categories

Resources