0

I got this code that fetches floats from a database.

for (int i = 0; i < ingredient.size() ; i++) {
    Ingredient ing = (Ingredient) ingredient.get(i);
    ingredients += String.valueOf(ing.getAmount()) + " " +
                   ing.getUnit() + " " + ing.getIngredient() + "\n";
}

The database is written in REAL values as some of them is 1.5, 2.5, 1.4 etc. But we also have these whole numbers without the need of a decimal, such as 1, 4, 10 etc. The problem is that the database table needs to be in REAL value, which gives us no choice but to give all the values one decimal, no matter if it's needed or not.

So we'll end up with values like: 1.0 1.5 2.3 20.0 5.0

My question is: How do we remove the unnecessary decimals, but keep the ones that need it?

weston
  • 54,145
  • 21
  • 145
  • 203
Kim Kakan Andersson
  • 548
  • 1
  • 5
  • 15

6 Answers6

1

One very simple way to remove these would be to strip the characters using StringUtils.

String displayValue = String.valueOf(ing.getAmount());

displayValue = StringUtils.stripEnd(displayValue, ".0");

For an input of "1.0", "1" will be returned.

A more technical approach would be to use the modulus operator %

For example:

if(value%1 == 0){  //1 divides into number perfectly, there is no decimal
    //cast value to integer or another non decimal variable
} else {
    //use existing value as it contains a decimal
}
Paddyd
  • 1,870
  • 16
  • 26
0

Convert your String returned from ing.getAmount() to a Float object, then use the modulo function to determine whether your value is an exact multiple of 1 (ie no decimal places). If so, convert your Float object to an int, which will concatenate the decimals.

Float f = Float.valueOf(ing.getAmount());
if(f%1 == 0) {
    // Use f.intValue() to concatenate your decimals.
    ingredients +=String.valueOf(f.intValue() + " " + ing.getUnit() + " " + ing.getIngredient() + "\n";
}
else {
    ingredients +=String.valueOf(ing.getAmount()) + " " + ing.getUnit() + " " + ing.getIngredient() + "\n";
}

I hope this helps.

Rudi Kershaw
  • 12,332
  • 7
  • 52
  • 77
0

How about this (does't require any fancy things like StringUtils)?

    String s = String.valueOf(1.0);
    System.out.println(s);

    /* Make this block as a function and return an int */
    String ss = " ";
    if (s.charAt(s.length()-2) == '.' && s.charAt(s.length()-1) == '0'){
        ss = s.substring(0,s.length()-2);
        System.out.println(ss);
    }
    /**************************************************/
    int converted = Integer.parseInt(ss);
    System.out.println(converted);

}

If you want to make it a function block, you can.

You can check it working on IDEONE - http://ideone.com/udJv8M

ha9u63a7
  • 6,233
  • 16
  • 73
  • 108
0

Check the float values with modulo. If 0 is returned it is an Integer. Here is an example with the numbers you have mentioned:

    List<Float> values = new ArrayList<Float>();
    values.add(new Float(1.0f));
    values.add(new Float(1.5f));
    values.add(new Float(2.3f));
    values.add(new Float(20.0f));
    values.add(new Float(5.0f));

    List<String> strValues = new ArrayList<String>();

    for(Float value : values)
    {
        String strValue = "";
        if(value % 1 == 0)
        {
            Integer intValue = value.intValue();
            strValue = intValue.toString();
            strValues.add(strValue);
        }
        else
        {
            strValue = value.toString();
            strValues.add(strValue);
        }

        System.out.println(strValue);
    }
JanTheGun
  • 2,165
  • 17
  • 25
0

You can use a custom DecimalFormat pattern:

public static String customFormat(String pattern, double value) {
    DecimalFormat myFormatter = new DecimalFormat(pattern);
    return myFormatter.format(value);
}

Then a pattern of # defines places holders for optional digits, so #.### will give up to 3 digits where necessary only.

for (int i = 0; i < ingredient.size() ; i++) {
    Ingredient ing = (Ingredient) ingredient.get(i);
    ingredients += customFormat("#.###", ing.getAmount()) +
                   " " + ing.getUnit() + " " + ing.getIngredient() + "\n";
}
weston
  • 54,145
  • 21
  • 145
  • 203
0

So don't convert your data to a String except for display only. Real numbers can represent both integers and floating point numbers using the same data type. Plus if you ever needed to do any math on your numbers you can't use Strings to do that. If you convert your numbers from the database directly to String before storing them into Ingredient then you've screwed yourself later on if you want to do calculations on those numbers. (Say you wanted to add a feature to double a recipe and have all of the quantities change for the user). Under your current plan you're preventing yourself from doing something like that because you're overly focused on the display of that number.

Instead just create a method on Ingredient to convert your numbers using String.format(). Like so:

 public class Ingredient {
     private double amount;
     private String name;

     public String asDecimal() {
         return String.format("%.1f", amount);
     }

     public String asInteger() {
         return String.format("%.0f", amount);
     }

     public String asFraction() {
         // exercise left to the reader
     }
 }

You could even add a function that converts decimals to fractional amounts to make it easier to display things chiefs might understand vs decimals which are harder. Bear in mind String.format() will round floating point amounts (0.5 -> 1 using as Integer).

chubbsondubs
  • 37,646
  • 24
  • 106
  • 138