182

I'm getting in an int with a 6 digit value. I want to display it as a String with a decimal point (.) at 2 digits from the end of int. I wanted to use a float but was suggested to use String for a better display output (instead of 1234.5 will be 1234.50). Therefore, I need a function that will take an int as parameter and return the properly formatted String with a decimal point 2 digits from the end.

Say:

int j= 123456 
Integer.toString(j); 

//processing...

//output : 1234.56
TylerH
  • 20,799
  • 66
  • 75
  • 101
daverocks
  • 2,293
  • 5
  • 19
  • 23
  • 1
    `String str = Integer.toString(j); //integer or string with white spaces
    str = new StringBuffer(str.trim()).insert(str.length()-2, ".").toString();`
    – user881703 Sep 27 '18 at 05:48

14 Answers14

242

As mentioned in comments, a StringBuilder is probably a faster implementation than using a StringBuffer. As mentioned in the Java docs:

This class provides an API compatible with StringBuffer, but with no guarantee of synchronization. This class is designed for use as a drop-in replacement for StringBuffer in places where the string buffer was being used by a single thread (as is generally the case). Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations.

Usage :

String str = Integer.toString(j);
str = new StringBuilder(str).insert(str.length()-2, ".").toString();

Or if you need synchronization use the StringBuffer with similar usage :

String str = Integer.toString(j);
str = new StringBuffer(str).insert(str.length()-2, ".").toString();
TylerH
  • 20,799
  • 66
  • 75
  • 101
blo0p3r
  • 6,790
  • 8
  • 49
  • 68
  • 1
    This solution works for any string >= 4 characters: the string "111" gave me ".111", and anything less than that results in a `java.lang.StringIndexOutOfBoundsException` (attempting to access a reference that doesn't exist). – sotrh Oct 17 '14 at 20:42
221
int j = 123456;
String x = Integer.toString(j);
x = x.substring(0, 4) + "." + x.substring(4, x.length());
Mike Thomsen
  • 36,828
  • 10
  • 60
  • 83
  • 7
    Strings are immutable. While this works, using something like StringBuilder is morally correct, not to mention will make your code faster. – wheresmycookie Jul 20 '13 at 19:39
  • 8
    Forget StringBuilder. With formatting such as this, [String.format](http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#format%28java.lang.String,%20java.lang.Object...%29) is the best option available. – NobleUplift Jul 24 '13 at 16:06
  • 36
    There is no loop, it's a simple concatenation case and compiler should optimize it using a string builder, for readability I prefer to use the + operator, there is no need in this case to use StringBuilder explicitly. Using "StringBuilder" solution because it's faster don't respect optimization rules. Code for readability. Optimize after profiling and only where it is require. http://en.wikipedia.org/wiki/Program_optimization#Quotes – Remi Morin Oct 07 '13 at 20:06
  • 18
    You do not need x.length() on the second substring call. – crazyGuy Jan 28 '16 at 14:07
  • 1
    This solution will fail when the number is a different number of digits. For 12345 it will output 1234.5 and for 1234567 it will be 1234.567. If you always want the last 2 digits to be after the decimal point, the make sure the number has at least 3 digits and then do `x = x.substring(0, x.length()-2) + "." + x.substring(x.length()-2);` – Teodor Marinescu Sep 07 '18 at 11:26
16
int yourInteger = 123450;
String s = String.format("%6.2f", yourInteger / 100.0);
System.out.println(s);
Simon Baars
  • 1,877
  • 21
  • 38
Itay Maman
  • 30,277
  • 10
  • 88
  • 118
  • I would suggest using `java.math.BigDecimal` as using `double` can cause [rounding error](http://stackoverflow.com/questions/177506/why-do-i-see-a-double-variable-initialized-to-some-value-like-21-4-as-21-3999996). If speed is more valuable than precision `double` is better. – sotrh Oct 17 '14 at 20:46
8

Using ApacheCommons3 StringUtils, you could also do

int j = 123456;
String s = Integer.toString(j);
int pos = s.length()-2;

s = StringUtils.overlay(s,".", pos, pos);

it's basically substring concatenation but shorter if you don't mind using libraries, or already depending on StringUtils

gherkin
  • 476
  • 7
  • 24
7

In most use-cases, using a StringBuilder (as already answered) is a good way to do this. However, if performance matters, this may be a good alternative.

/**
 * Insert the 'insert' String at the index 'position' into the 'target' String.
 * 
 * ````
 * insertAt("AC", 0, "") -> "AC"
 * insertAt("AC", 1, "xxx") -> "AxxxC"
 * insertAt("AB", 2, "C") -> "ABC
 * ````
 */
public static String insertAt(final String target, final int position, final String insert) {
    final int targetLen = target.length();
    if (position < 0 || position > targetLen) {
        throw new IllegalArgumentException("position=" + position);
    }
    if (insert.isEmpty()) {
        return target;
    }
    if (position == 0) {
        return insert.concat(target);
    } else if (position == targetLen) {
        return target.concat(insert);
    }
    final int insertLen = insert.length();
    final char[] buffer = new char[targetLen + insertLen];
    target.getChars(0, position, buffer, 0);
    insert.getChars(0, insertLen, buffer, position);
    target.getChars(position, targetLen, buffer, position + insertLen);
    return new String(buffer);
}
rmuller
  • 12,062
  • 4
  • 64
  • 92
6

For Kotlin dudes ;) from the accepted answer (@MikeThomsen's)

fun String.insert(insertAt: Int, string: String): String {
    return this.substring(0, insertAt) + string + this.substring(insertAt, this.length)
}

Test ✅

"ThisTest".insert(insertAt = 4, string = "Is").should.equal("ThisIsTest")
theapache64
  • 10,926
  • 9
  • 65
  • 108
3

String.format("%0d.%02d", d / 100, d % 100);

kkurian
  • 3,844
  • 3
  • 30
  • 49
  • 2
    To whoever downvoted this: Re-read what the OP described in detail. This provides an exact answer to the problem: No floating point math. Puts the decimal point in the right place. To wit, https://stackoverflow.com/a/5884413/972128 provides a similar answer but uses floating point (not desired), and has 17 upvotes at this time. – kkurian Jan 31 '20 at 20:27
2

You could use

System.out.printf("%4.2f%n", ((float)12345)/100));

As per the comments, 12345/100.0 would be better, as would the use of double instead of float.

Joseph Ottinger
  • 4,911
  • 1
  • 22
  • 23
  • 2
    `double` might be a better choice. float is only accurate to 6 digits. – Peter Lawrey May 04 '11 at 14:10
  • 1
    Yeah, another example someone responded with was to use 12345/100.0, which is smarter (although it ends up with the same result.) – Joseph Ottinger May 04 '11 at 14:11
  • Nitpicking: I think this wont't give the right result, because 12345/100 = 123 in integer and is only cast to 123.00 afterwards. ((float)12345/100) would work. – rurouni May 05 '11 at 13:20
  • Heh, good point - I wasn't taking the precedence into account, mostly because the very first time he ran it it'd give him the truncated result. Will fix the post (which used to say 12345/100, then cast the result, instead of widening the value first.) – Joseph Ottinger May 05 '11 at 13:46
0

I think a simpler and more elegant solution to insert a String in a certain position would be this one-liner:

target.replaceAll("^(.{" + position + "})", "$1" + insert);

For example, to insert a missing : into a time String:

"-0300".replaceAll("^(.{3})", "$1:");

What it does is, matches position characters from the beginning of the string, groups that, and replaces the group with itself ($1) followed by the insert string. Mind the replaceAll, even though there's always one occurrence, because the first parameter must be a regex.

Of course it does not have the same performance as the StringBuilder solution, but I believe the succinctness and elegance as a simple and easier to read one-liner (compared to a huge method) is sufficient for making it the preferred solution in most non performance-critical use-cases.

Note I'm solving the generic problem in the title for documentation reasons, of course if you are dealing with decimal numbers you should use the domain-specific solutions already proposed.

Luan Nico
  • 5,376
  • 2
  • 30
  • 60
0

If you are using a system where float is expensive (e.g. no FPU) or not allowed (e.g. in accounting) you could use something like this:

    for (int i = 1; i < 100000; i *= 2) {
        String s = "00" + i;
        System.out.println(s.substring(Math.min(2, s.length() - 2), s.length() - 2) + "." + s.substring(s.length() - 2));
    }

Otherwise the DecimalFormat is the better solution. (the StringBuilder variant above won't work with small numbers (<100)

rurouni
  • 2,315
  • 1
  • 19
  • 27
  • 2
    In the case of accounting, you'd be better off with BigDecimal. – Joseph Ottinger May 04 '11 at 14:07
  • @Joseph: You are right. I'm not in accounting and I mostly use ints as a fixedpoint representation for performance reasons (in embedded java), so BigDecimal is not my choice ;-) – rurouni May 04 '11 at 14:35
0

There are good answers here, but with Kotlin extensions addition we can do it even more simply:

    val indexWhereInsertIsIntended = 2
    val inputString = "2408"
    val resultingString = inputString.toCharArray().toMutableList()
        .also { 
             it.add(indexWhereInsertIsIntended, '/') 
        }.joinToString("")

Result = 24/08

This example shows a card expiry date, and slash (/) is intended at 2nd Index. So the resulting index in this case will have / at 2nd index.

If you want to replace and not add:

val indexWhereInsertIsIntended = 2
        val inputString = "2408"
        val resultingString = inputString.toCharArray()
            .also { 
                 it[indexWhereInsertIsIntended] = '/' 
            }.joinToString("")

Result = 24/0

Wajid
  • 2,235
  • 1
  • 19
  • 29
-1
  public static void main(String[] args) {
    char ch='m';
    String str="Hello",k=String.valueOf(ch),b,c;

    System.out.println(str);

    int index=3;
    b=str.substring(0,index-1 );
    c=str.substring(index-1,str.length());
    str=b+k+c;
}
Miya
  • 11
  • 1
-1
// Create given String and make with size 30
String str = "Hello How Are You";

// Creating StringBuffer Object for right padding
StringBuffer stringBufferRightPad = new StringBuffer(str);
while (stringBufferRightPad.length() < 30) {
    stringBufferRightPad.insert(stringBufferRightPad.length(), "*");
}

System.out.println("after Left padding : " + stringBufferRightPad);
System.out.println("after Left padding : " + stringBufferRightPad.toString());

// Creating StringBuffer Object for right padding
StringBuffer stringBufferLeftPad = new StringBuffer(str);
while (stringBufferLeftPad.length() < 30) {
    stringBufferLeftPad.insert(0, "*");
}
System.out.println("after Left padding : " + stringBufferLeftPad);
System.out.println("after Left padding : " + stringBufferLeftPad.toString());
  • 2
    Welcome to Stack Overflow! Generally, answers are much more helpful if they include an explanation of what the code is intended to do, and why that solves the problem without introducing others. Thanks for improving the answer's reference value and making it more understandable! – Tim Diekmann Jun 20 '18 at 14:05
  • Please don't use StringBuffer as it was replaced by StringBuilder in 2004. – Peter Lawrey Jun 22 '18 at 19:55
-2

Try this :

public String ConvertMessage(String content_sendout){

        //use unicode (004E00650077) need to change to hex (&#x004E&#x;0065&#x;0077;) first ;
        String resultcontent_sendout = "";
        int i = 4;
        int lengthwelcomemsg = content_sendout.length()/i;
        for(int nadd=0;nadd<lengthwelcomemsg;nadd++){
            if(nadd == 0){
                resultcontent_sendout = "&#x"+content_sendout.substring(nadd*i, (nadd*i)+i) + ";&#x";
            }else if(nadd == lengthwelcomemsg-1){
                resultcontent_sendout += content_sendout.substring(nadd*i, (nadd*i)+i) + ";";
            }else{
                resultcontent_sendout += content_sendout.substring(nadd*i, (nadd*i)+i) + ";&#x";
            }
        }
        return resultcontent_sendout;
    }