Страницы

Поиск по вопросам

Показаны сообщения с ярлыком format. Показать все сообщения
Показаны сообщения с ярлыком format. Показать все сообщения

понедельник, 30 декабря 2019 г.

Вывод double с нужной точностью и в нужном формате

#cpp #строки #stl #double #format


Требуется вывести double с максимальной точностью, при этом целую часть, которая
не превышает 999 вывести с пробелами на месте отсутствующих цифр, типа 9,12...

Вывожу следующим образом

std::cout << std::fixed << std::setprecision(std::numeric_limits::digits10
+ 1) << value << std::endl;


Возникло 2 проблемы:

1) везде читал, что точность double определяется как std::numeric_limits::digits10,
однако похоже, что можно вытащить больше значащих цифр, если задать точность в 20 цифр,
то будут видны все 20 отличных от 0 цифр

2) не нашел, как можно задать размер целой части, чтобы заполнить отсутствующие цифры
пробелами

Подскажите, что требуется сделать?
    


Ответы

Ответ 1



Всё, чего вам не хватало, это задать заполнитель setfill и ширину setw выводимого поля: #include #include #include void print(double value) { const auto digits = std::numeric_limits::digits10; std::cout << std::setfill(' ') << std::setw(digits + 4); std::cout << std::fixed << std::setprecision(digits) << value << std::endl; } int main() { double value = 9.12; print(value); } Результат выполнения

Ответ 2



Можно также написать класс, с функциональностью выводить как угодно. Например: #include #include #include using namespace std; class IM { double d; size_t ww; char c; public: IM(double val, size_t whole_size, char imbue = ' ') : d(val), ww(whole_size), c(imbue) {} int get_whole() const { return d; } int get_fraction() const { stringstream s; s << d - get_whole(); int k; s.ignore(2); // пропускаем '0' и '.' s >> k; return k; } friend ostream& operator <<(ostream& os, const IM& m) { os << setw(m.ww) << setiosflags(ios_base::left) <

Ответ 3



Во-первых, смысл величины digits10 для плавающего типа T заключается в том, что если вы возьмете десятичное строковое представление, преобразуете его в значение типа T, а затем преобразуете его из T обратно в десятичное строковое представление, то вы получите digits10 значащих цифр цифр, совпадающих с вашей исходной строкой. Например, если вы используете плавающий тип для хранения целых значений, то целые значения с таким количеством цифр будут представляться без потерь, как и соседние (+-1) целые значения. Родственной величиной является величина max_digits10, которая говорит, что если вы преобразуете плавающее значение типа T в десятичное строковое представление с сохранением max_digits10 старших значащих цифр, а затем преобразуете его обратно в тип T, то вы гарантированно получите исходное значение типа T. Таким образом, величина digits10 описывает сохранение данных в преобразовании туда-обратно вида "строка10 -> плавающее -> строка10". А величина max_digits10 описывает сохранение данных в преобразовании туда-обратно вида "плавающее -> строка10 -> плавающее". Это, однако, совсем не означает, что десятичное строковое плавающее значение будет иметь только столько точных цифр. Огульно обзывать цифры за пределами этого количества "мусором" - очевидная профанация. Какие цифры являются точными, а какие нет - определяется спецификой ваших вычислений и известно только вам. Очевидный пример: "традиционные" двоичные плавающие типы способны точно представлять степени двойки в пределах возможностей экспоненты. То есть std::pow(2, 512) даст вам точное значение типа double 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096 в котором намного больше значащих цифр, чем digits10 или max_digits10 для double (15 и 17 соответственно). Никакого "мусора" в этом представлении нет (разумеется, если вы хотели вычислить именно 2512) . Вас это не должно удивлять. Умение пользоваться такими возможностями плавающих представлений - это во многом и есть умение пользоваться плавающими типами в общем. Во-вторых, что касается управления шириной поля при выводе - об этом вы уже получили ответы.

Ответ 4



По ходу обсуждения оказалось, что имеет смысл остановиться подробнее на определении точности вещественного типа. Удивительно, но оказывается, что точность double совсем не жалкие 15 цифр, а намного, намного больше! И в подтверждение приводятся числа 2^(-100) и 2^512, которые действительно представляются точно. Так что же, получается что и в самом деле точность double больше, чем 15 цифр? К сожалению нет, такие заявления говорят лишь о непонимании вещественной арифметики. Давайте посмотрим на представление чисел вещественным типом. Точность представления определяется его мантиссой, которая в случае числа двойной точности имеет длину 52 бита и соответственно может представить 2^52 значений. Теперь возьмем некое число, у которого в двоичном представлении биты мантиссы 53, 54, и т.д. являются нулями. Нетрудно видеть, что такое число будет представлено абсолютно точно. С бесконечной точностью! И таких чисел существует ровно 2^52. Попробуем теперь немного уменьшить требования к точности. Возьмем, скажем, тысячу знаков после запятой - есть ли числа, которые представляются с такой точностью? Да, такие числа в самом деле есть, и из свойств множества действительных чисел видно, что их бесконечно много. Какую бы точность мы ни задали - сто, тысячу, миллион знаков после запятой, - оказывается, что существует бесконечно много чисел, представимых именно с такой точностью. Получается, что точность вещественного типа это какая-то странная характеристика, которая произвольно меняется в зависимости от числа вплоть до бесконечности? Нет, именно в этом месте и происходит путаница! Точность представления отдельно взятого числа не имеет никакого отношения к точности вещественного типа. Слово одно, но под ним подразумеваются совершенно разные вещи. А собственно точность представления числа, хотя и кажется очень важной с бытовой точки зрения, в вещественной арифметике никакого значения не имеет. По той простой причине, что она непредсказуема - мы не можем определить точность представления по результату вычислений. Для этого надо этот результат сравнить с эталонным значением, а если мы и так его знаем, то зачем нам что-то вычислять? Так что же такое точность вещественного типа? Представим, что у нас есть два числа, у которых первые 52 бита мантиссы совпадают, а различается бит 53. Эти два числа будут представлены одной и той же мантиссой, и соответственно, тем же самым числом двойной точности. Мы говорим, что точность double составляет 52 бита, и это означает простую вещь: double различает только числа, у которых отличаются первые 52 бита. Числа, у которых отличаются только биты 53 и последующие, представляются одной и той же мантиссой. Вот это и есть точность! Соответственно,в десятичном виде точность double составляет 15.45 десятичных цифр. Это означает, что числа, отличающиеся первыми 15 знаками всегда представляются разными значениями double. Числа с отличиями в 16-ом знаке могут представляться разными значениями (в 45% случаев), а могут и не отличаться (соответственно, в 55% случаев). Числа с отличием в 17-ом и более младших знаках имеют одинаковое представление в числе двойной точности. Разумеется, тема точности вещественной арифметики немного сложнее этого простого определения. Для более серьезного ознакомления можно посоветовать Д. Кнут, том 2 "Получисленные алгоритмы", глава 4.2.2 "Точность выполнения арифметических действий в системе с плавающей точкой".

пятница, 20 декабря 2019 г.

Как проигнорировать фигурные скобки в функции string.Format

#c_sharp #net #строки #format


Как проигнорировать фигурные скобки в функции string.Format?
Пример:

string.Format("{Name:{0}}", "Value");


В результате выполнения данного кода мы получим исключение


  An unhandled exception of type 'System.FormatException' occurred in mscorlib.dll 
  
  Additional information: Input string was not in a correct
  format.


Что нужно сделать, для того, чтобы избавится от ошибки и получить в результате строку:

{Name:Value}

    


Ответы

Ответ 1



Открытие и закрытие скобок интерпретируется как начальный и конечный элемент для функции форматирования строки. Для того чтобы вывести фигурную скобку в строке нужно ее продублировать {{ для открытия скобки и }} для ее закрытия. Исправленный вариант будет выглядеть следущим образом: string.Format("{{Name:{0}}}", "Value"); Детали можно посмотреть на MSDN, а также тут

четверг, 19 декабря 2019 г.

произвести замену в шаблоне по условию

#python #python_3x #format


Нужно сформатировать строку (желательно методом format). Строка, например, такая:

string = "words{hello||hello1}words"


А до этой строки задается параметр s=True или s=False, и если s=True, то на выходе
должна получиться вот что:

string = 'wordshellowords'


, а если s=False, то:

string = 'wordshello1words'


Как это сделать?
    


Ответы

Ответ 1



Алгоритм по шагам: string = "words{hello||hello1}words" start = string.index('{') + 1 end = string.index('}') replace_str = string[start: end] print(replace_str) # hello||hello1 var_replace = replace_str.split('||') print(var_replace) # ['hello', 'hello1'] string = string.replace(replace_str, '') print(string) # words{}words s = True if s: new_string = string.format(var_replace[0]) print(new_string) # wordshellowords else: new_string = string.format(var_replace[1]) print(new_string) # wordshello1words В виде функции: def foo(string: str, s=True) -> str: start, end = string.index('{') + 1, string.index('}') replace_str = string[start: end] var_replace = replace_str.split('||') string = string.replace(replace_str, '') # Можно схитрить, т.к. True -- 1, False -- 0 # return string.format(var_replace[not s]) return string.format(var_replace[0] if s else var_replace[1]) string = "words{hello||hello1}words" print(foo(string, True)) # wordshellowords print(foo(string, False)) # wordshello1words Вариант через регулярку: import re def foo(string: str, s=True) -> str: def _on_match(match): var_replace = match.group()[1:-1].split('||') return var_replace[0] if s else var_replace[1] return re.sub('{.+?}', _on_match, string) string = "words{hello||hello1}words" print(foo(string, True)) # wordshellowords print(foo(string, False)) # wordshello1words

Ответ 2



Чтобы выбрать при замене в шаблоне первую альтернативу, когда first=True: import re format_spec = "words{AAA||BBB}words" first = True print(re.sub( "{([^}]+)}", lambda match: match.group(1).split("||")[not first], format_spec, )) Результат: wordsAAAwords Здесь используется, что True == 1, а False == 0, поэтому булевы переменные могут использоваться в качестве индексов. К примеру, [1, 2][True] возвращает 2, а [1, 2][False] возвращает 1.

Ответ 3



string = "wordshello{}words" s = True print(string.format(int(s) or '')) # 'wordshello1words' s = False print(string.format(int(s) or '')) # 'wordshellowords'

Ответ 4



string = 'words{}words' subs = ['hello1', 'hello'] s = True print(string.format(subs[s])) # wordshellowords Трюк в том, что при преобразовании в целое число True станет 1, а False – 0, и таким образом выбираем элемент по индексу.

Ответ 5



import re string = 'words{hello||hello1}words' parts = re.split(r'[{|}]', string) if s == True: print(parts[0] + parts[1] + parts[-1]) else: print(parts[0] + parts[-2] + parts[-1])

суббота, 14 декабря 2019 г.

Форматирование целого числа из “12345678” в “12 345 678”

#java #android #format


Как сделать форматирование числа из "12345678" в "12 345 678". То есть нужно каждую
1000 отделить пробелом, что бы большие числа выглядели эстетично.
    


Ответы

Ответ 1



Попробуйте так: NumberFormat f = NumberFormat.getInstance(); int i = 12345678; System.out.println(f.format(i)); // 12 345 678 P.S. Как здесь справедливо заметили, итоговый результат будет зависеть от текущей локали. Для того, чтобы не зависело, нужно указать конкретную локаль: NumberFormat f = NumberFormat.getInstance(new Locale("ru", "RU")); Список локалей и представления чисел в этих локалях можно посмотреть здесь

Ответ 2



Ещё один способ, без создания лишних объектов: String.format(Locale.CANADA_FRENCH, "%,d", 1234567890); Результат 1 234 567 890

Ответ 3



Решение независящее от локали: DecimalFormat formatter=new DecimalFormat(); DecimalFormatSymbols symbols=DecimalFormatSymbols.getInstance(); symbols.setGroupingSeparator(' '); //явно задаем символ разделителя тысяч formatter.setDecimalFormatSymbols(symbols); int i=12345678; String s=formatter.format(i).toString(); //12 345 678 P.S. можно написать более красиво через конструктор DecimalFormat с паттерном задающим символы локализации DecimalFormatSymbols - специально привел в длинном виде, чтобы была понятна логика.

понедельник, 17 декабря 2018 г.

Как проигнорировать фигурные скобки в функции string.Format

Как проигнорировать фигурные скобки в функции string.Format? Пример:
string.Format("{Name:{0}}", "Value");
В результате выполнения данного кода мы получим исключение
An unhandled exception of type 'System.FormatException' occurred in mscorlib.dll Additional information: Input string was not in a correct format.
Что нужно сделать, для того, чтобы избавится от ошибки и получить в результате строку:
{Name:Value}


Ответ

Открытие и закрытие скобок интерпретируется как начальный и конечный элемент для функции форматирования строки. Для того чтобы вывести фигурную скобку в строке нужно ее продублировать {{ для открытия скобки и }} для ее закрытия. Исправленный вариант будет выглядеть следущим образом:
string.Format("{{Name:{0}}}", "Value");
Детали можно посмотреть на MSDN, а также тут