6

I thought I could accomplish this easily with something such as the following:

double numInput;

numInput = Double.parseDouble(inputTxtField.getText());

if ((numInput * 100) % 1 != 0) {

// do something

}

However, I'm getting all sorts of strange test cases where such as:

false: 2.11, 2.5, 2.6

true: 2.22, 2.3, 2.2

I just started programming so maybe this is a silly goof, but I thought multiplying a double by 100 and then checking for a remainder when dividing by 1 would work. The intent is to prevent someone from entering a number with more than two decimals. Less than or equal to 2 decimals is fine.

Any tips are appreciated! Thank you!

EDIT: Thank you for all the quick comments! This solved my problem, and I really appreciate the extra information as to why it won't work. Thank you!

Rumblebutt
  • 169
  • 1
  • 1
  • 4

4 Answers4

16

Convert to BigDecimal and check the scale:

double[] values = { 2.11, 2.5, 2.6, 2.22, 2.3, 2.2, 3.141 };
for (double value : values) {
    boolean fail = (BigDecimal.valueOf(value).scale() > 2);
    System.out.println(value + "  " + (fail ? "Fail" : "Pass"));
}

Output

2.11  Pass
2.5  Pass
2.6  Pass
2.22  Pass
2.3  Pass
2.2  Pass
3.141  Fail
Andreas
  • 154,647
  • 11
  • 152
  • 247
  • This would be the correct approach. `new BigDecimal(String.valueOf(doubleNumber)).scale() > 2`. Ref: https://www.baeldung.com/java-separate-double-into-integer-decimal-parts – Shanika Ediriweera Sep 03 '20 at 06:43
  • @ShanikaEdiriweera The [`BigDecimal.valueOf(double val)`](https://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html#valueOf-double-) used in the answer is implemented as `return new BigDecimal(Double.toString(val));`, so what this old answer shows **is** the *correct approach*, and has been since it was added in **Java 1.5**. It uses the convenience method, supplied by the Java Runtime Library, to keep the code simpler. – Andreas Sep 03 '20 at 08:16
3

Try

if(inputTxtField.getText().indexOf(".") >= 0 && inputTxtField.getText().indexOf(".") < inputTxtField.getText().length() - 2){

It will be true when there is a decimal in the original String that is before the last 2 characters in the String.

cbender
  • 2,231
  • 1
  • 14
  • 18
  • This fails if user types `123.4500`, even though that number is technically good. – Andreas Sep 11 '15 at 21:00
  • 1
    @Andreas: The question was about checking that there were 2 decimal places, which isn't true for that input, even if they are zeros. Even if your input is valid, it can be solved by things like making a regex that allows any number of zeros at the end. Anyway, the general idea of validating the input text is much saner than converting it to a double and then trying to reason about it, +1. – Nathan Hughes Sep 11 '15 at 21:02
  • @NathanHughes The question is "double **variable** has more than two decimals". The question isn't asking how to check the text field, even though that is the source of the value. Now, a good answer can suggest that *as an alternative*, but this answer deviated from the question without notice. – Andreas Sep 11 '15 at 21:11
  • 1
    @Andreas: since the OP seems to be unaware of the representation issues I think it's hard to know what the question really is about. – Nathan Hughes Sep 11 '15 at 21:44
3

This won't work. Computers work in binary. Remember that 1/3 equals 0.33333333 with infinite digits. The computer can only store a finite number of binary digits, so it cuts after some digits. This means that 1/3 * 3 != 1. Same goes for any number in binary, that means 1/100 * 100 is not 1, because you just lost some decimal places. Working with double you will never be able to use the standard = or != operators, because they won't work most of the time.

The best way to solve this in your case is to work with the String directly and look at the position of the '.' character.

HopefullyHelpful
  • 1,652
  • 3
  • 21
  • 37
0

Try using compareTo from the Double class

Double numInput;
Double foo = numInput*100;
foo = foo - foo.intValue();

if (foo.compareTo(0D) > 0 ) {

   //has more than two digits

}
brlaranjeira
  • 367
  • 2
  • 11