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
daverocks
fonte
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());
Mike Thomsen
fonte
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();
blo0p3r
fonte
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);
Itay Maman
fonte
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);
}
rmuller
fonte
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

pepino
fonte
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.

Joseph Ottinger
fonte
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)

rurouni
fonte
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.

Luan Nico
fonte
0

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

kkurian
fonte
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")
theapache64
fonte
-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;
}
Miya
fonte
-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());
Nagendra Mishra
fonte
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;
    }
Pattanai Pornpibul
fonte