51

I have Strings (from DB), which may contain numeric values. If it contains numeric values, I'd like to remove trailing zeros such as:

  • 10.0000
  • 10.234000

str.replaceAll("\\.0*$", ""), works on the first one, but not the second one.

A lot of the answers point to use BigDecimal, but the String I get may not be numeric. So I think a better solution probably is through the Regex.

Kent
  • 189,393
  • 32
  • 233
  • 301
fivelements
  • 1,487
  • 2
  • 19
  • 32

12 Answers12

103

there are possibilities:

1000    -> 1000
10.000  -> 10 (without point in result)
10.0100 -> 10.01 
10.1234 -> 10.1234

I am lazy and stupid, just

s = s.indexOf(".") < 0 ? s : s.replaceAll("0*$", "").replaceAll("\\.$", "");

Same solution using contains instead of indexOf as mentioned in some of the comments for easy understanding

 s = s.contains(".") ? s.replaceAll("0*$","").replaceAll("\\.$","") : s
Markus
  • 3,155
  • 2
  • 23
  • 33
Kent
  • 189,393
  • 32
  • 233
  • 301
27

Use DecimalFormat, its cleanest way

String s = "10.1200";
DecimalFormat decimalFormat = new DecimalFormat("0.#####");
String result = decimalFormat.format(Double.valueOf(s));
System.out.println(result);
Srujan Kumar Gulla
  • 5,721
  • 9
  • 48
  • 78
  • And surely also the slowest (and maybe even the most complicated?). – maaartinus Sep 23 '14 at 13:59
  • @maaartinus why is this complicated? As someone who doesn't know regex very well, I can understand this code and adapt it to what I need. Regex may be faster, but syntax-wise, it's just a mess to me. – TheWanderer Aug 29 '18 at 20:41
  • @TheWanderer On the second thought, I mostly agree with you. The regex is actually pretty simple (and I'd recommend to learn regexes at this level), but more complicated regexes get too messy too fast. – maaartinus Aug 30 '18 at 15:20
17

Kent's string manipulation answer magically works and also caters for precision loss, But here's a cleaner solution using BigDecimal

String value = "10.234000";
BigDecimal stripedVal = new BigDecimal(value).stripTrailingZeros();

You can then convert to other types

String stringValue = stripedVal.toPlainString();
double doubleValue = stripedVal.doubleValue();
long longValue = stripedVal.longValue();

If precision loss is an ultimate concern for you, then obtain the exact primitive value. This would throw ArithmeticException if there'll be any precision loss for the primitive. See below

int intValue = stripedVal.intValueExact();
Komoo
  • 301
  • 3
  • 8
  • Not exactly what OP asked (does not work for non-numeric values) but exactly what I needed - thank you! – domids Nov 25 '21 at 11:23
11
String value = "10.010"
String s = new DecimalFormat("0.####").format(Double.parseDouble(value));
System.out.println(s);

Output:

   10.01
PAC
  • 1,664
  • 1
  • 18
  • 24
  • 10
    Hiya there, while this may well answer the question, please be aware that other users might not be as knowledgeable as you. Why don't you add a little explanation as to why this code works? Thanks! – Vogel612 Apr 13 '15 at 11:11
7

I find all the other solution too complicated. Simply

s.replaceFirst("\\.0*$|(\\.\\d*?)0+$", "$1");

does the job. It tries the first alternative first, so that dot followed by all zeros gets replaced by nothing (as the group doesn't get set). Otherwise, if it finds a dot followed by some digits (as few as possible due to the lazy quantifier *?) followed by some zeros, the zeros get discarded as they're not included in the group. It works.

Warning

My code relies on my assumption that appending a unmatched group does nothing. This is true for the Oracle implementation, but not for others, including Android, which seem to append the string "null". I'd call the such implementations broken as it just may no sense, but they're correct according to the Javadoc.

Community
  • 1
  • 1
maaartinus
  • 44,714
  • 32
  • 161
  • 320
3

The following works for all the following examples:

"1" -> "1"
"1.0" -> "1"
"1.01500" -> "1.015"
"1.103" -> "1.103"

s = s.replaceAll("()\\.0+$|(\\..+?)0+$", "$2");
Dipen Shah
  • 1,911
  • 10
  • 29
  • 45
Pit
  • 31
  • 1
0

What about replacing

(\d*\.\d*)0*$

by

\1

?

alestanis
  • 21,519
  • 4
  • 48
  • 67
0

You could replace with:

String result = (str.indexOf(".")>=0?str.replaceAll("\\.?0+$",""):str);

To keep the Regex as simple as possible. (And account for inputs like 1000 as pointed out in comments)

mdm
  • 3,928
  • 3
  • 27
  • 43
  • Right. I just thought of "trailing zeros". Not to the mathematical representation of the number. My bad. In this case, Kent's answer (checking for "." before applying Regex) is more correct. – mdm Feb 20 '13 at 17:19
0

My implementation with possibility to select numbers of digits after divider:

public static String removeTrailingZero(String number, int minPrecise, char divider) {
    int dividerIndex = number.indexOf(divider);

    if (dividerIndex == -1) {
        return number;
    }

    int removeCount = 0;
    for (int i = dividerIndex + 1; i < number.length(); i++) {
        if (number.charAt(i) == '0') {
            removeCount++;
        } else {
            removeCount = 0;
        }
    }

    int fracLen = number.length() - dividerIndex - 1;

    if (fracLen - removeCount < minPrecise) {
        removeCount = fracLen - minPrecise;
    }

    if (removeCount < 0) {
        return number;
    }

    String result = number.substring(0, number.length() - removeCount);

    if (result.endsWith(String.valueOf(divider))) {
        return result.substring(0, result.length() - 1);
    }

    return result;
}
Vadim
  • 3,855
  • 2
  • 17
  • 22
0

In addition to Kent's answer.

Be careful with regex in Kotlin. You have to manually write Regex() constructor instead of a simple string!

s = if (s.contains(".")) 
        s.replace(Regex("0*\$"),"").replace(Regex("\\.\$"),"") 
    else s
coldembrace
  • 549
  • 8
  • 19
0

Try to use this code:

DecimalFormat df = new DecimalFormat("#0.#####");

String value1 = df.format(101.00000);
String value2 = df.format(102.02000);
String value3 = df.format(103.20000);
String value4 = df.format(104.30020);

Output:

101
102.02
103.2
104.3002
Subarata Talukder
  • 5,407
  • 2
  • 34
  • 50
-1

Separate out the fraction part first. Then you can use the below logic.

BigDecimal value = BigDecimal.valueOf(345000);
BigDecimal div = new BigDecimal(10).pow(Integer.numberOfTrailingZeros(value.intValue()));
System.out.println(value.divide(div).intValue());
Anand
  • 1