Як вставити символ у рядок у певній позиції?


155

Я отримую int6-значне значення. Я хочу відобразити його як знак Stringз десятковою комою (.) У двох цифрах з кінця int. Я хотів використовувати, floatале було запропоновано використовувати Stringдля кращого результату відображення (замість 1234.5буде 1234.50). Тому мені потрібна функція, яка буде приймати intяк параметр і повертати належним чином відформатований двоцифровий розряд Stringз кінця.

Сказати:

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

Відповіді:


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

6
Струни незмінні. Хоча це працює, використання чогось типу StringBuilder є морально правильним, не кажучи вже про те, що ваш код буде швидшим.
wheresmycookie

7
Забудьте StringBuilder. З таким форматуванням, як String.format - найкращий варіант.
NobleUplift

33
Немає циклу, це простий випадок конкатенації, і компілятор повинен оптимізувати його за допомогою конструктора рядків, для читабельності я вважаю за краще використовувати оператор +, в цьому випадку немає необхідності явно використовувати StringBuilder. Використання рішення "StringBuilder", оскільки воно швидше не дотримується правил оптимізації. Код для читабельності. Оптимізуйте після профілювання та лише там, де цього потрібно. en.wikipedia.org/wiki/Program_optimization#Quotes
Ремі Морін

17
Для виклику другої підрядки вам не потрібно x.length ().
crazyGuy

1
Це рішення не вдасться, коли число є різною кількістю цифр. Для 12345 він виведе 1234,5, а для 1234567 - 1234,567. Якщо ви завжди хочете, щоб останні дві цифри були після десяткової крапки, переконайтеся, що число має принаймні 3 цифри, а потім зробіть цеx = x.substring(0, x.length()-2) + "." + x.substring(x.length()-2);
Теодор Марінеску

210

Як зазначалося в коментарях, StringBuilder , ймовірно, швидша реалізація, ніж використання StringBuffer . Як зазначено в документах Java:

Цей клас надає API, сумісний зі StringBuffer, але без гарантії синхронізації. Цей клас розроблений для використання в якості замінного для заміни StringBuffer у місцях, де буфер рядків використовувався одним потоком (як це зазвичай буває). Там, де це можливо, рекомендується використовувати цей клас на користь StringBuffer, оскільки він буде швидшим у більшості реалізацій.

Використання:

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

Або якщо вам потрібна синхронізація, використовуйте StringBuffer з подібним використанням:

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

1
Це рішення працює для будь-якого рядка> = 4 символи: рядок "111" дав мені java.lang.StringIndexOutOfBoundsException.
sotrh

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

Я б сказав, що використання java.math.BigDecimalяк використання doubleможе спричинити помилку округлення . Якщо швидкість більш цінна, то точність, doubleтим краще.
sotrh

5

У більшості випадків використання StringBuilder(як уже відповіли) є хорошим способом зробити це. Однак, якщо результативність має значення, це може бути хорошою альтернативою.

/**
 * 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

Використовуючи ApacheCommons3 StringUtils, ви також можете зробити

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

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

це в основному підрядка конкатенації, але коротше, якщо ви не проти використовувати бібліотеки або вже залежно від StringUtils


2

Ви можете використовувати

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

Відповідно до коментарів, 12345 / 100.0 було б краще, як і використання double, а не float.


2
doubleможе бути кращим вибором. float точний лише до 6 цифр.
Пітер Лорі

1
Так, ще один приклад, з яким хтось відповів, - це використовувати 12345 / 100.0, що розумніше (хоча в кінцевому підсумку такий же результат)
Джозеф Оттінгер

Нітпікінг: Я думаю, що це не дасть правильного результату, тому що 12345/100 = 123 у цілому чирі та надається лише 123,00 згодом. ((float) 12345/100) спрацювало б.
rurouni

Хе, хороший момент - я не брав до уваги перевагу, головним чином тому, що в перший раз, коли він його провів, це дало б йому усічений результат. Виправить повідомлення (яке раніше говорили 12345/100, потім передасть результат, а не розширити спочатку значення)
Джозеф Оттінгер

0

Якщо ви використовуєте систему, де float є дорогим (наприклад, відсутність FPU) або заборонено (наприклад, у бухгалтерському обліку), ви можете використовувати щось подібне:

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

Інакше DecimalFormat є кращим рішенням. (Версія StringBuilder вище не працюватиме з невеликими цифрами (<100)


2
Що стосується бухгалтерського обліку, вам буде краще з BigDecimal.
Джозеф Оттінгер

@ Джозеф: Ви праві. Я не в бухгалтерському обліку, і я здебільшого використовую ints як фіксовану точку представлення з міркувань продуктивності (у вбудованій Java), тому BigDecimal - це не мій вибір ;-)
rurouni

0

Я думаю, що більш простим і елегантним рішенням вставити рядок у певному положенні буде такий однолінійний:

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

Наприклад, щоб вставити пропущене :у строку:

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

Що це робиться - це відповідність positionсимволів з початку рядка, групи, які замінюють групу собою ($1 ), а потімinsert рядок. Майте на увазі замінуAll, хоча завжди є одне виникнення, тому що першим параметром повинен бути регулярний вираз.

Звичайно, воно не має такої ж продуктивності, як рішення StringBuilder, але я вважаю, що лаконічність і елегантність як простого і легшого для читання однолінійки (порівняно з величезним методом) є достатнім, щоб зробити його кращим рішенням у більшості неефективних -критичні випадки використання.

Примітка. Я вирішую загальну задачу в заголовку з причин документації, звичайно, якщо ви маєте справу з десятковими числами, ви повинні використовувати вже запропоновані рішення для домену.


0

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


Кому хто це прихильнив: Перечитайте детально описані ОП. Це дає точну відповідь на проблему: Немає математики з плаваючою комою. Поставте десяткову точку в потрібне місце. На думку, stackoverflow.com/a/5884413/972128 дає аналогічну відповідь, але використовує плаваючу крапку (не бажано), і наразі має 17 відгуків.
kkurian

0

Для котлінських хлопців;) з прийнятої відповіді (@ MikeThomsen's)

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

Тест ✅

"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
Ласкаво просимо до переповнення стека! Як правило, відповіді набагато корисніші, якщо вони включають пояснення того, що призначений для виконання коду та чому це вирішує проблему, не вводячи інших. Дякуємо за те, що покращили опорне значення відповіді та зробили її більш зрозумілою!
Тім Дікманн

Будь ласка, не використовуйте StringBuffer, оскільки його замінили StringBuilder в 2004 році.
Пітер Лоурі

-2

Спробуйте це :

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;
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.