2

I have a String value which can either hold a Long or a Double. The String may be Locale based.

So it may hold the following values:

11
11.00
15,25 (for Locale like Denmark where the decimal part is denoted by a comma instead of dot)

I want to do something only when it is a Double; in sense that it contains a fraction value. A fraction value of "00" is also a valid case.

if(string contains fraction){
  // do something
}

Given above three examples, control should go inside if for 11.00 and 15,25 but not for 11.

How can I check this?

Please keep in mind that Locale is involved. So dot and comma may have different meaning for different Locale. So simple regex to find their occurrence won't work. For e.g. 11,00 is 1100 if Locale is Australia and thus is not a double. But 11,00 is a double if Locale is a European country like Denmark or Germany.

I need to find some solution using NumberFormat but not able to work it out.

I have Locale info. So I know if the String is of which Locale. Given that, how can I find if String has a fraction or not?

Vicky
  • 16,679
  • 54
  • 139
  • 232
  • 1
    So check if it contains not only digits ? or chekc if contains comma or dot ? – azro Aug 01 '18 at 07:23
  • Why don't you try `Double.parseDouble` and check for `NumberFormatException`? – gcandal Aug 01 '18 at 07:24
  • 1
    @gcandal you'd need to parse using two `Locale`s if either decimal point or comma might be the separator. – daniu Aug 01 '18 at 07:25
  • if its a string, why can't to search for comma or dot or write a regex. what is the difficulty here. I dont understand – pvpkiran Aug 01 '18 at 07:25
  • @pvpkiran: as daniu said, since Locale is involved, comma and dot can have different meaning for different Locale. I can't make decision just by using regex to search for comma or dot. – Vicky Aug 01 '18 at 07:26
  • @Nik now I get your point. Can you add that in the question. So that it is helpful for anyine reading it – pvpkiran Aug 01 '18 at 07:27
  • Possible duplicate of [Java validate price with comma or dot and two decimal value](https://stackoverflow.com/questions/17804887/java-validate-price-with-comma-or-dot-and-two-decimal-value) – pvpkiran Aug 01 '18 at 07:29
  • @pvpkiran: No. It is not duplicate of that question. Did you even read the question correctly ? Please don't be in a hurry ... – Vicky Aug 01 '18 at 07:32
  • @Nik but the idea is same, you can use the same regex to match your string – pvpkiran Aug 01 '18 at 07:34
  • @pvpkiran: no I cannot. If my Locale is Australia and the String is 11,00 then it should not enter the "if" and 1100 is not a double and has no fraction. – Vicky Aug 01 '18 at 07:36
  • 2
    how do you make the difference between 11,001 english and 11,001 of denmark so ? Without more info your problem is not solvable – azro Aug 01 '18 at 07:36
  • @Nik How can 11,00 be 1100 even in australian local ? I downvote this question you give some requirement that are not solvable for the info you give. Example as 11,001 England and 11,001 Denmark. – azro Aug 01 '18 at 07:39
  • 1
    @Nik which Locale applies? The one of the VM? Or is it provided as a parameter somehow? – Malte Hartwig Aug 01 '18 at 07:40
  • NumberFormat nf = NumberFormat.getNumberInstance(Locale.anything) – Vicky Aug 01 '18 at 07:41
  • @MalteHartwig: Yes. I have locale information. Please read last line of the question – Vicky Aug 01 '18 at 07:42
  • 3
    Have a look at [this question](https://stackoverflow.com/questions/4713166/decimal-separator-in-numberformat). In the comments to the accepted answer, they mention `new DecimalFormatSymbols(myLocale).getDecimalSeparator()` which should enable you to build the correct regex. – Malte Hartwig Aug 01 '18 at 07:44
  • The question [How to format double value for a given locale and number of decimal places?](https://stackoverflow.com/questions/10411414/how-to-format-double-value-for-a-given-locale-and-number-of-decimal-places) and [this answer](https://stackoverflow.com/a/10416264/2838289) to it should help you to get along. – LuCio Aug 01 '18 at 07:55
  • @Nik I've made an edit to my post. See if this helps you. :) – Kevin Cruijssen Aug 01 '18 at 08:13
  • @MalteHartwig: Thanks. DecimalSeparator might work for me. Thanks. – Vicky Aug 01 '18 at 10:22
  • Hope it helps. Maybe you should add an answer yourself later to wrap this question up. Might help someone in the future. – Malte Hartwig Aug 01 '18 at 10:28

3 Answers3

1

With a regex you could do

Pattern decimalPattern = Pattern.compile("\\d+(,|\\.)\\d+{2}");

and then have

boolean isDecimal = decimalPattern.matcher(input).matches();

Regex:

  • \d+ one or more digits
  • (,|\\.) a decimal point or a comma
  • \d+ one or more digits again

Or you could do the splitting thing

String[] split = input.split("(,|\\.)");
boolean isDecimal = split.length > 1 && split[1].length() == 2;
daniu
  • 14,137
  • 4
  • 32
  • 53
1

EDIT: Since you've edited your question stating you know the Locale, you can use it with NumberFormat.getNumberInstance(locale).parse(strValue) in combination with a regex for the comma and thousand separator. Here a test code:

import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;

class Main{
  private static final Locale DUTCH = new Locale("nl","NL");

  public static void main(String[] a){
    test("11", Locale.ENGLISH);
    test("11", DUTCH);
    System.out.println();
    test("11.00", Locale.ENGLISH);
    test("11.00", DUTCH);
    System.out.println();
    test("11,00", Locale.ENGLISH);
    test("11,00", DUTCH);
    System.out.println();
    test("15.123", Locale.ENGLISH);
    test("15.123", DUTCH);
    System.out.println();
    test("15,123", Locale.ENGLISH);
    test("15,123", DUTCH);
    System.out.println();
    test("something", Locale.ENGLISH);
    test("something", DUTCH);
  }

  static void test(String val, Locale locale){
    try{
      DecimalFormatSymbols symbols = new DecimalFormatSymbols(locale);
      char decimalSep = symbols.getDecimalSeparator();
      char thousandSep = symbols.getGroupingSeparator();

      String escapedDecimalSep = decimalSep == '.' ? "\\." : decimalSep+"";
      String escapedThousandSep = thousandSep == '.' ? "\\." : thousandSep+"";

      String intRegex = "\\d+(" + escapedThousandSep + "\\d{3})*"; // Example ENGLISH: "\\d+(,\\d{3})*"
      String doubleRegex = intRegex + escapedDecimalSep + "\\d+"; // Example ENGLISH: "\\d+(,\\d{3})*\\.\\d+"

      NumberFormat format = NumberFormat.getInstance(locale);
      Number number = format.parse(val);
      if(val.matches(doubleRegex)){
        double d = number.doubleValue();
        System.out.println(val + " (in locale " + locale + ") is a double: " + d);
      } else if(val.matches(intRegex)){
        int i = number.intValue();
        System.out.println(val + " (in locale " + locale + ") is an integer: " + i);
      } else{
        System.out.println("Unable to determine whether value " + val + " is an integer or double for locale " + locale);
      }
    } catch(ParseException ex){
      System.out.println("Error occurred for value \"" + val + "\". Are you sure it's an integer or decimal?");
    }
  }
}

Try it online.

Here is the output:

11 (in locale en) is an integer: 11
11 (in locale nl_NL) is an integer: 11

11.00 (in locale en) is a double: 11.0
Unable to determine whether value 11.00 is an integer or double for locale nl_NL

Unable to determine whether value 11,00 is an integer or double for locale en
11,00 (in locale nl_NL) is a double: 11.0

15.123 (in locale en) is a double: 15.123
15.123 (in locale nl_NL) is an integer: 15123

15,123 (in locale en) is an integer: 15123
15,123 (in locale nl_NL) is a double: 15.123

Error occurred for value "something". Are you sure it's an integer or decimal?
Error occurred for value "something". Are you sure it's an integer or decimal?
Kevin Cruijssen
  • 9,153
  • 9
  • 61
  • 135
  • Thanks.. but this is what I am doing and struggling with. 11,00 should not return as Integer but as Double because it has fraction (even though 00). – Vicky Aug 01 '18 at 10:21
  • @Nik I've edited again. This time it uses a combination of both the Number-parse and regex. – Kevin Cruijssen Aug 01 '18 at 11:51
0

You could use a loop to check if it have a comma or dot and then check with the if?

boolean IsADouble = false;
for (int i = 0; i < String.length(); i++) {
            if (String.charAt(i) == ','|| String.charAt(i) == '.') {
                IsADouble = true
            }
        }

And then you create the If to do something if its a double.

Hope it helped you :)

GonzaloPani
  • 170
  • 15
  • 11,000 for English Locale is not a double value but will return true for your solution. – Vicky Aug 01 '18 at 07:35
  • So you could add more conditions to be true, like if is a double probably is gonna have only 2 zeros. Adapt this way to your code, I think it could work @Nik – GonzaloPani Aug 01 '18 at 07:38