Home > Software design >  Determine the most fitting numeric variable type for a String
Determine the most fitting numeric variable type for a String

Time:04-14

I'm trying to create Predicates to test Strings and determine the most appropriate variable type, which means I want to get the "smallest" numeric variable type that the parsed String fits into.

So for example, for a String "-1.2" the detected type should be float, but if the number exceeds the float range, it should detect double. If the number is even bigger, then BigDecimal.

For non-floating point numbers my tests seem to work fine, but the decimal numbers are giving me more headaches than they should.

This is my isFloat test:

Predicate<String> isFloat =
    s -> {
      try {
        Double d = Double.parseDouble(s);
        return d >= -Float.MAX_VALUE && d <= Float.MAX_VALUE;
      } catch (Exception e) {
        return false;
      }
    };

String minOfFloat = String.valueOf(-Float.MAX_VALUE);
System.out.println(minOfFloat);
System.out.println(Double.parseDouble(minOfFloat));
System.out.println(isFloat.test(minOfFloat));

Outputs:

-3.4028235E38
-3.4028235E38
false //WHYYYYY

Similarly my next test would be to check if the number fits a double, and if not, return "BigDecimal".

What's the correct way to test this?

EDIT: This is the way I'm doing it, accepted answer brought me there:

public static final Predicate<String> isFloat =
  s -> {
    try {
      Double d = Double.parseDouble(s);
      
      return d.floatValue() >= -Float.MAX_VALUE
          && d.floatValue() <= Float.MAX_VALUE
          && !Float.isInfinite(d.floatValue())
          && !Float.isNaN(d.floatValue());
    } catch (Exception e) {
      return false;
    }
  };

CodePudding user response:

Change your predicate to compare with d.floatValue() >= -Float.MAX_VALUE && d <= Float.MAX_VALUE;

In case, if your double value exceeds float range d.floatValue() returns infinity so you should be good with the change

 Predicate<String> isFloat = s -> {
            try {
                Double d = Double.parseDouble(s);
                return d.floatValue() >= -Float.MAX_VALUE && d <= Float.MAX_VALUE;
            } catch (Exception e) {
                return false;
            }
        };
    String maxDouble = String.valueOf(Double.MAX_VALUE);
    System.out.println(maxDouble);
    System.out.println(isFloat.test(maxDouble));

CodePudding user response:

Using BigDecimal is recomended when widening primitive conversion will be applied. I couldn't find a good duplicate, but see this posts

how-to-compare-correctly-long-and-float-primitives

comparing-float-and-double-primitives-in-java

to understand why you might get wrong results when comparing two different types. So I would do something like:

Predicate<String> isFloat = 
   str -> new BigDecimal(str).compareTo(new BigDecimal(String.valueOf(Float.MAX_VALUE))) <= 0 &&
          new BigDecimal(str).compareTo(new BigDecimal(String.valueOf(-Float.MAX_VALUE))) >= 0;
  • Related