0

I'm having two float numbers, they can be decimals or not, depending on the operation I want to print the result either with decimal or without.

I'm using String.format to take off the decimal when not needed. However, I have trouble identifying when the result will be decimal. Tried the n1 % n2 > 0 method from a similar question, but when entering for example 6 + 7 the result becomes 13.0 instead of just 13.

Code so far:

    float n1 = Float.parseFloat(request.getParameter("num1").toString().trim());
    float n2 = Float.parseFloat(request.getParameter("num2").toString().trim());

    String res = String.valueOf(n1+n2);

    if(n1 % n2 > 0)
        {
           out.println("It's decimal");
           out.println(n1+n2);
        }else{
           out.println(String.format("%.0f", n1+n2));
        }
Midori_hige
  • 311
  • 6
  • 21
  • Why not parsing the sum as Integer and compare both sums (float and integer). If they are the same it means the sum is not decimal. – Alfredo May 21 '16 at 05:09
  • 1
    Possible duplicate of [How to check if number is a decimal?](http://stackoverflow.com/questions/14799943/how-to-check-if-number-is-a-decimal) – PseudoAj May 21 '16 at 05:11
  • @pseudoAJ tried the answer from that question, but as I said on my edit it didnt work. – Midori_hige May 21 '16 at 05:23
  • 1
    If your question is only about an output display issue (so it will show `13` or `14.5` depending), [there is one approach here](http://stackoverflow.com/questions/703396/how-to-nicely-format-floating-numbers-to-string-without-unnecessary-decimal-0). – KevinO May 21 '16 at 05:23
  • Please learn the correct terminology. A real number (or `float`) can be an integer or not--but "decimal" is not a correct term to mean a non-integer. Your question was rather confusing to me for a while, since "decimal" basically means base 10, and I thought you were asking how to tell whether a number is in base 10. – ajb May 21 '16 at 05:33
  • @pseudoAJ I don't think this is a duplicate of that question. That question asks how to tell whether _division between two integers_ gives a non-integer, but there's no division in this example, so the solution is very different. – ajb May 21 '16 at 05:36
  • The code is somewhat confusing. @Midori_hige do you want to tell if `n1` is divisible by `n2` or if the sum of both numbers has a decimal fraction? – dpr May 21 '16 at 06:29
  • @dpr if it has a decimal fraction. – Midori_hige May 24 '16 at 19:04
  • @Midori_hige than I don't understand why you are checking for `n1 % n2 > 0` instead of `(n1+n2)%1 > 0`. If you take a look at my answer this check corresponds to the commented if-statement `res.stripTrailingZeros().scale() > 0`. – dpr May 24 '16 at 19:08
  • @Midori_hige, has this question been answered for you? If yes, would you mind to accept the most helpful answer to mark this question as solved (see [here](http://stackoverflow.com/help/someone-answers))... Thanks – dpr Jun 16 '16 at 09:30

4 Answers4

0

You can use Math.round to tell if a float is an integer. (There are other approaches if your only purpose is to suppress the decimal point for integers when formatting as a string--see KevinO's comment.)

If f is a float, Math.round(f) returns an int, which is f rounded to the nearest integer, unless f is outside the range of an int. However, if f is outside the range of an int, then f must be an integer, for all practical purposes--if f is large enough that it is too big to fit in an int, then it's too big to distinguish between values that are less than 1.0 apart (there are fewer bits of precision in a float than in an int). So there's no way for f to represent a non-integer of that magnitude.

Given that, and assuming that f isn't +/- infinity, you can test whether f is an integer like this:

public boolean isInteger(float f) {
    return f > (float)Integer.MAX_VALUE ||
           f < (float)Integer.MIN_VALUE ||
           f == (float)Math.round(f);
}

But please note that even a non-integer could appear as something.000000 when you format it, since the formatter will have to round f to a certain number of decimal places when printing. It depends on what kind of format you're using.

NOTE: The above method is a correct way to determine whether a float is an integer, if the float is the only information you have. However, in the context of a larger program, there are other considerations. If the parameter string is "2000000000.1", when you parse it as a float you will get 2000000000, which is an integer, because the float doesn't have enough precision to represent the .1. At that point, your float will be an integer value, and it's too late for it to know about the .1--that information has been lost. If you don't want to lose that information, then don't use float or double--use BigDecimal instead.

ajb
  • 31,309
  • 3
  • 58
  • 84
0

For doing exact math with non-integers (numbers with fractions) in Java you should use BigDecimal. This class allows for exact representation of non-integers of arbitrary precision.

That is your code should be changed to:

final BigDecimal n1 = new BigDecimal(request.getParameter("num1").toString().trim());
final BigDecimal n2 = new BigDecimal(request.getParameter("num2").toString().trim());

final BigDecimal res = n1.add(n2);
final BigDecimal remainder = n1.remainder(n2);

//if (res.stripTrailingZeros().scale() > 0) {
if (remainder.compareTo(BigDecimal.ZERO) != 0) {
    System.out.println("It's decimal");
    System.out.println(res);
} else {
    final DecimalFormat df = new DecimalFormat("#.0f");
    System.out.println(df.format(res));
}

The other answer will not give you the correct result, if a user inputs a number larger than Integer.MAX_VALUE or lower than Integer.MIN_VALUE. Casting to long will probably yield wrong results due to the precision of float that might cause the result to have a decimal fraction even if the input numbers did not...

However I hope you're doing some input validation of the request data. Otherwise you'll most likely get a lot of NumberFormatExceptions from your JSP-page.

UPDATE: Updated the code example to check for scale instead of precision.

dpr
  • 10,591
  • 3
  • 41
  • 71
0

Cast to int then back:

boolean isDecimal = myFloat != (float)(int)myFloat;

Casting to int truncates the decimal part.


Or, you can use a string approach. Decimals have non-zero digits after the dot, so:

boolean isDecimal = String.valueOf(myFloat).matches(".*\\.(?=.*[1-9]).*");
Bohemian
  • 412,405
  • 93
  • 575
  • 722
0

If you just need that for output, the easiest approach is probably to do this with string manipulation:

String s = String.format("%.4f", n1 + n2);  // use whatever decimal places you like
s = s.replaceFirst("\\.0*$", "");
System.out.println(s);

This will fail if the decimal separator in your Locale is , instead of ., so be careful.

To really check if a double value x is integral you can use this test:

if (x % 1 == 0) {
    // integral
} else {
    // not integral
}
Henry
  • 42,982
  • 7
  • 68
  • 84