Como inserir um caractere em uma string em uma determinada posição?


155

Estou entrando intcom um valor de 6 dígitos. Quero exibi-lo como um Stringcom um ponto decimal (.) A 2 dígitos do final de int. Eu queria usar um, floatmas foi sugerido para usar Stringpara uma melhor saída de exibição (em vez de 1234.5será 1234.50). Portanto, preciso de uma função que aceite um intparâmetro as e retorne o formatado corretamenteString com um ponto decimal 2 dígitos no final.

Dizer:

int j= 123456 
Integer.toString(j); 

//processing...

//output : 1234.56

1
String str = Integer.toString(j); //integer or string with white spaces<br/> str = new StringBuffer(str.trim()).insert(str.length()-2, ".").toString();
user881703

Respostas:


195
int j = 123456;
String x = Integer.toString(j);
x = x.substring(0, 4) + "." + x.substring(4, x.length());

6
Strings são imutáveis. Enquanto isso funciona, usar algo como StringBuilder é moralmente correto, sem mencionar, tornará seu código mais rápido.
wheresmycookie

7
Esqueça o StringBuilder. Com uma formatação como essa, String.format é a melhor opção disponível.
NobleUplift

33
Não há loop, é um caso simples de concatenação e o compilador deve otimizá-lo usando um construtor de strings; para facilitar a leitura, prefiro usar o operador +; nesse caso, não é necessário usar o StringBuilder explicitamente. Usar a solução "StringBuilder" porque é mais rápido não respeita as regras de otimização. Código de legibilidade. Otimize após a criação de perfil e somente onde for necessário. en.wikipedia.org/wiki/Program_optimization#Quotes
Remi Morin

17
Você não precisa de x.length () na segunda chamada de substring.
precisa saber é o seguinte

1
Esta solução falhará quando o número tiver um número diferente de dígitos. Para 12345, ele produzirá 1234,5 e, para 1234567, será 1234,567. Se você sempre quer os últimos 2 dígitos para ser depois do ponto decimal, a garantir que o número tem pelo menos 3 dígitos e, em seguida, fazerx = x.substring(0, x.length()-2) + "." + x.substring(x.length()-2);
Teodor Marinescu

210

Como mencionado nos comentários, um StringBuilder é provavelmente uma implementação mais rápida do que o uso de um StringBuffer . Conforme mencionado nos documentos Java:

Esta classe fornece uma API compatível com StringBuffer, mas sem garantia de sincronização. Essa classe foi projetada para ser usada como um substituto para o StringBuffer nos locais em que o buffer da string estava sendo usado por um único encadeamento (como geralmente é o caso). Sempre que possível, é recomendável que essa classe seja usada preferencialmente ao StringBuffer, pois será mais rápida na maioria das implementações.

Uso:

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

Ou se você precisar de sincronização, use o StringBuffer com uso semelhante:

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

1
Esta solução funciona para qualquer cadeia de caracteres> = 4 caracteres: a cadeia "111" me forneceu ".111" e qualquer coisa menor que isso resulta em um java.lang.StringIndexOutOfBoundsException(tentativa de acessar uma referência que não existe).
sotrh

17
int yourInteger = 123450;
String s = String.format("%6.2f", yourInteger / 100.0);
System.out.println(s);

Eu sugeriria usar java.math.BigDecimalcomo usar doublepode causar erro de arredondamento . Se a velocidade é mais valiosa do que a precisão, doublemelhor.
sotrh

5

Na maioria dos casos de uso, usar um StringBuilder(como já respondido) é uma boa maneira de fazer isso. No entanto, se o desempenho importa, essa pode ser uma boa alternativa.

/**
 * 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);
}

4

Usando o ApacheCommons3 StringUtils, você também pode fazer

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

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

é basicamente concatenação de substring, mas mais curta se você não se importa em usar bibliotecas ou já depende de StringUtils


2

Você poderia usar

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

De acordo com os comentários, 12345 / 100.0 seria melhor, assim como o uso de double em vez de float.


2
doublepode ser uma escolha melhor. float tem precisão de apenas 6 dígitos.
Peter Lawrey

1
Sim, outro exemplo de alguém respondeu com era usar 12345 / 100.0, que é mais inteligente (embora ele acaba com o mesmo resultado.)
Joseph Ottinger

Nitpicking: Eu acho que isso não dará o resultado certo, porque 12345/100 = 123 em número inteiro e só é convertido em 123,00 depois. ((flutuante) 12345/100) funcionaria.
Rurouni 5/05

Heh, bom ponto - eu não estava levando em consideração a precedência, principalmente porque a primeira vez que ele executava isso dava a ele o resultado truncado. Irá corrigir o post (que costumava dizer 12345/100, depois converter o resultado, em vez de aumentar o valor primeiro).
Joseph Ottinger

0

Se você estiver usando um sistema em que o float é caro (por exemplo, sem FPU) ou não é permitido (por exemplo, na contabilidade), você pode usar algo como isto:

    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));
    }

Caso contrário, o DecimalFormat é a melhor solução. (a variante StringBuilder acima não funcionará com números pequenos (<100)


2
No caso da contabilidade, você estaria melhor com o BigDecimal.
Joseph Ottinger

@ Joseph: Você está certo. Eu não estou na contabilização e eu principalmente usar ints como uma representação fixedpoint por motivos de desempenho (em Java embutido), de modo BigDecimal não é minha escolha ;-)
rurouni

0

Eu acho que uma solução mais simples e mais elegante para inserir uma String em uma determinada posição seria esta linha:

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

Por exemplo, para inserir uma :String ausente no tempo:

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

O que ele faz é corresponder positioncaracteres desde o início da sequência, agrupar e substituir o grupo por si mesmo ( $1) seguido pela insertsequência. Observe o replaceAll, mesmo que sempre exista uma ocorrência, porque o primeiro parâmetro deve ser uma regex.

É claro que ele não tem o mesmo desempenho que a solução StringBuilder, mas acredito que a sucessão e a elegância de uma linha única simples e mais fácil de ler (em comparação com um método enorme) são suficientes para torná-la a solução preferida na maioria dos que não são de desempenho casos de uso críticos.

Nota: Estou resolvendo o problema genérico no título por motivos de documentação; é claro que se você estiver lidando com números decimais, deverá usar as soluções específicas de domínio já propostas.


0

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


Para quem desvalorizou isso: Releia o que o OP descreveu em detalhes. Isso fornece uma resposta exata para o problema: Sem matemática de ponto flutuante. Coloca o ponto decimal no lugar certo. A saber, stackoverflow.com/a/5884413/972128 fornece uma resposta semelhante, mas usa ponto flutuante (não desejado) e tem 17 votos positivos no momento.
kkurian 31/01

0

Para Kotlin caras;) a partir da resposta aceita (@ MikeThomsen's)

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

Teste ✅

"ThisTest".insert(4, "Is").should.equal("ThisIsTest")

-2
  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;
}

-2
// 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
Bem-vindo ao Stack Overflow! Geralmente, as respostas são muito mais úteis se incluem uma explicação sobre o que o código pretende fazer e por que isso resolve o problema sem a introdução de outros. Obrigado por melhorar o valor de referência da resposta e torná-lo mais compreensível!
precisa

Por favor, não use StringBuffer como ele foi substituído por StringBuilder em 2004.
Peter Lawrey

-2

Tente o seguinte:

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;
    }
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.