Как из float сделать string c
Перейти к содержимому

Как из float сделать string c

  • автор:

Как конвертировать float/double в строку именно в том виде, в котором значение устновленно в переменной (без обрезки занков)?

Выводит «0.01234567», а надо «0.012345678900000». stringstream пробовал — результат тот же. std::to_string вообще 6 знаков пишет после точки. Точность заранее не известна, нужно выгружать в строку то, что есть, можно без нулей в конце. Как это сделать?

Отслеживать
задан 8 мая 2020 в 18:27
2,273 1 1 золотой знак 17 17 серебряных знаков 27 27 бронзовых знаков
А вы не задумывались, какова точность представления числа типом float ?
8 мая 2020 в 18:29
@Harry с double картина не меняется
8 мая 2020 в 18:31
Ну, вы вообще бредом занимаетесь — в пустой string что-то писать.
8 мая 2020 в 18:35

Ну, конкретное количество нулей справа — это вы никак не получите. У гугла есть библиотека, которая печататет числа с плавающей точкой за минимальное количество знаков, возможно это вам подойдет. (По идее, std::to_chars тоже должна так уметь, но пока ее завезли только в MSVC.)

8 мая 2020 в 18:58

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

float valf = 0.012345678900100; double vald = 0.012345678900100; printf("%.20f\n", valf); printf("%.20lf\n", vald); 
0.01234567910432815552 0.01234567890010000030 

В любом случае в силу того, что числа с плавающей точкой представлены в итоге виде суммы степеней двойки, ожидать, что введенный строковый литерал или результат вычисления будет равен чему-то конкретному, не приходится.

char buf[30]; sprintf(buf,"%.20lf",val); string s = buf; 
ostringstream os; os  

Только не пишите в никуда, как в вашем примере.

Update

К "артефактам", упомянутым в комментарии. Это не артефакты. Представим, что у нас есть возможность записи только 4 бит. Как вы представите, например, 1/5 в виде суммы дробей вида 1/2 n ?

1/8 + 1/16 + 1/128. Стоп! Уже не можем представить 1/128 - точности не хватает. Так что число 0.20 будет иметь вид 0.1875.

Это - ограничение самого представления. Ну невозможно в общем случае представить дробное число с помощью конечной суммы дробей вида 1/2 n .

Как из float сделать string c

Нередко может возникнуть необходимость объединить строку с данными других типов, например, числами. Однако объединить строку мы можем только с другой строкой. Поэтому данные других типов вначале необходимо преобразовать в строку. Для преобразования в строку применяется функция std:to_string() , в которую передается преобразуемое значение:

#include #include int main() < unsigned age; std::string message< "Age: " + std::to_string(age)>; std::cout 

Функции преобразования из строки в число

Нередко может вощникнуть противиположная задача - преобразовать строку в другой тип. Есть ряд функций, которые преобразуют строку в число определенного типа:

  • stoi() : преобразует в тип int
  • stol() : в long
  • stoll() : в long long
  • stoul() : в unsigned long
  • stoull() : в unsigned long long
  • stof() : в float
  • stod() : в double
  • stold() : в long double

Все они определены в модуле , работают однотипно и в качестве параметра принимают преобразуемую строку:

std::string str< "123" >; int n< std::stoi(str) >; // n == 123

Преобразование строки в указатель на символы

При необходимости можно преобразовать значение типа string в указатель на символы. Для преобразования в указатель на константную строку применяется метод c_str() :

#include #include int main() < std::string message ; const char* message_ptr = message.c_str(); // преобразуем в указатель std::cout

Для получения указателя также можно применять метод data() , который возвращает указатель на неконстантное значение, если объект string не является константой.

#include #include int main() < std::string message ; char* message_ptr = message.data(); // преобразуем в указатель std::cout

Arduino.ru

Здравствуйте! Сразу опишусь что я новичок в C++. Сейчас занимаюсь с модулем SIM900, библиотека такая http://github.com/amperka/gprs-shield/releases. И какой уже день не могу разобраться с отправкой температуры, записанной в переменную float.

void get_atmosph() < unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) < previousMillis = currentMillis; h = dht.readHumidity(); // читаем влажность // temp_f = dht.readTemperature(true); // читаем температуру в фаренгейтах t = dht.readTemperature(false); // читаем температуру в цельсиях // проверяем, что считалось pa = bmp.readPressure(); mmHg = pa / 133,32236842; >>

Дело в том что библиотека воспринимает текст смс-ки только в массиве char, размером до 160 символов.

else if (!String(message).compareTo("Temperature") && unread == true)

Если кто-то знает хоть какую-то ссылку на ресурс или даст кусок кода, то буду очень Вам благодарен.

  • Войдите на сайт для отправки комментариев

Сб, 20/01/2018 - 19:36

DIYMan аватар

Зарегистрирован: 23.11.2015

  • Войдите на сайт для отправки комментариев

Сб, 20/01/2018 - 22:00

ЕвгенийП аватар

Зарегистрирован: 25.05.2015

Конечно, можно и через класс String, раз уж Вы им всё равно пользуетесь (суде по показанному кусочку).

А чего, првда, через String не сделали?

  • Войдите на сайт для отправки комментариев

Вс, 21/01/2018 - 11:50
Алексей Кабанов
Зарегистрирован: 20.01.2018

Евгений, спасибо большое за помощь! Если подскажете как сделать через String это будет ещё лучше. Я просто этот код по кусочкам собирал и вместе с этим C++ учил, поэтому много ещё не знаю.

  • Войдите на сайт для отправки комментариев

Вс, 21/01/2018 - 12:09

ЕвгенийП аватар

Зарегистрирован: 25.05.2015
Алексей Кабанов пишет:

через String это будет ещё лучше

Я то покажу, мне не жалко, но лучше не будет - точно! String непростая вещь и для своего использования требует квалификации, которой Вы пока не обладаете. Но дело Ваше .

А там, собственно и делать-то нечего. Создаёте строку, передав в конструктор Ваш float и количество знаков после запятой, а потом берёте её c_str - вот Вам и массив char'ов

#include void setup(void) < Serial.begin(115200); // // Как-то вычисляем float // const float radius = 1.5; const float len = 2.0 * M_PI * radius; // // Теперь преобразуем len в строку с тремя // знаками после запятой и получаем массив char // < String sLen(len, 3); const char * szLen = sLen.c_str(); // szLen ссылается на массив char - печатаем Serial.println(szLen); >> void loop(void) <>

Скобки в строках 14 и 19, можно и опустить, на вид ничего не изменится, но лучше их ставить. Открывающую перед описанием String, а закрывающая тогда, когда созданный String больше не нужен и его можно выбросить. Подробности.

  • Войдите на сайт для отправки комментариев

Вс, 21/01/2018 - 12:13
Алексей Кабанов
Зарегистрирован: 20.01.2018

Ну всё равно спасибо! Хоть какая-то информация. Попробую её применить в своём скетче.

  • Войдите на сайт для отправки комментариев

Вс, 21/01/2018 - 12:32
Алексей Кабанов
Зарегистрирован: 20.01.2018

Евгений, спасибо, всё получилось! Теперь мой последний вопрос. Как склеить char равную "Temperature: " и char равную "27.51" в char равную "Temperature: 27.51"?

  • Войдите на сайт для отправки комментариев

Вс, 21/01/2018 - 14:57

ЕвгенийП аватар

Зарегистрирован: 25.05.2015

А что по отдельности передавать нельзя?

А чтобы Вам ответить, надо знать как Вы её собрались клеить? Из String'ов или из символьных массивов?

  • Войдите на сайт для отправки комментариев

Вс, 21/01/2018 - 15:02
Алексей Кабанов
Зарегистрирован: 20.01.2018

Клеить я буду из char'ов , а по отдельности передавать нельзя, потому что задача стоит сделать сообщение которое будет удобно читать пользователю.

  • Войдите на сайт для отправки комментариев

Вс, 21/01/2018 - 16:56

ЕвгенийП аватар

Зарегистрирован: 25.05.2015

Нет, давайте толком. Вы для преобразования используете String или dtostrf?

Просто, если там уж всё равно есть String, то проще им и склеить. А если нет (если сразу через dtostrf, то гуглите функции strcpy и strcat

  • Войдите на сайт для отправки комментариев

Сб, 03/02/2018 - 23:13
Алексей Кабанов
Зарегистрирован: 20.01.2018

Евгению и DIYMan'у огромное спасибо за помощь! Забыл я что-то выложить сюда свой готовый код. Ну вообщем вот он:

else if (!String(message).compareTo("Sensor") && unread == true) < Serial.println("New message"); h = dht.readHumidity(); // temp_f = dht.readTemperature(true); t = dht.readTemperature(false); pa = bmp.readPressure(); mmHg = pa / 133,32236842; Serial.println(t); String sT(t, 1); char * szT = sT.c_str(); String sH(h, 1); char * szH = sH.c_str(); String sMmHg(mmHg, 2); char * szMmHg = sMmHg.c_str(); const char *Temperature = "Temperature "; const char *degr = "*C "; const char *Humiduty = "Humiduty "; const char *perc = "% "; const char *Pressure = "Pressure "; const char *Hg = " mm Hg "; char data[512]; snprintf(data, sizeof data, "%s%s%s%s%s%s%s%s%s", Temperature, szT, degr, Humiduty, szH, perc, Pressure, szMmHg, Hg); gprs.sendSMS(phone, data); unread = false; Serial.println("Message send"); >

Извините что без комментариев в коде. Просто пока он не такой сложный я комментарии не пишу, да и вообще я не люблю комментарии. Думаю что кому-то из начинающих ардуинщиков мой код поможет!

Спасибо ещё раз за помощь и удачи!

  • Войдите на сайт для отправки комментариев

Сб, 03/02/2018 - 23:20

DIYMan аватар

Зарегистрирован: 23.11.2015
Алексей Кабанов пишет:

Просто пока он не такой сложный я комментарии не пишу, да и вообще я не люблю комментарии.

Распространённая ошибка. Поверьте, комментарии помогут вам через год-два, когда вы будете разбираться, что и как. Не брезгуйте комментариями. Небольшой жизненный секрет, существенно облегчающий написание кода, помогающий сразу его комментировать и структурировать: сначала - вы не пишете ни строчки кода, совсем. Вместо этого пишете комментарии, примерно вот так:

// читаем с датчика движения // если сработал // и мотор ещё не работает, то // выключаем помаргивающий светодиод // включаем мотор // запоминаем время начала работы мотора // выставляем флаг, что мотор работает // и выходим из обработчика // если не сработал // помаргиваем светодиодом, сигнализируя о готовности

Потом - начинаете между комментариями писать код, это становится проще сделать, т.к. вы уже человечьим языком описали алгоритм 😉

  • Войдите на сайт для отправки комментариев

float to string на эмбедах, без sprintf, как?

Посоветуйте, чем можно обычный float перегнать в строку, с заданной точностью? А то по всяким stackoverflow какие-то васянские снипеты и мутные самоделки с непонятными лицензиями. Сейчас юзаю sprintf, но он помимо жирности кастует float в double, что вызывает дополнтельное распухание зависимостей.

Мне не надо наворотов sprintf, хватило бы просто «распечатать с XX знаками после запятой», можно даже без отрицательных значений. Может есть какие-то известные библиотеки, от которых эмбед не треснет?

PS. Закопипастить 30 строк кода всегда успеется. Сначала хочу попробовать найти и заюзать библиотеку.

Vit ★★★★★
03.10.19 11:37:07 MSK

Сначала хочу попробовать найти и заюзать библиотеку.

Что там юзать? Сперва отсекаешь целое, потом берешь остаток, записываешь его в char* и делишь это целое в цикле на 10, пока не кончится. Дробную часть умножаешь на 10, пока не надоест, записывая целое в char*.

crutch_master ★★★★★
( 03.10.19 11:55:50 MSK )
Последнее исправление: crutch_master 03.10.19 11:56:51 MSK (всего исправлений: 1)

Заюзай xprintf же!

shkolnick-kun ★★★★★
( 03.10.19 12:37:45 MSK )
Ответ на: комментарий от shkolnick-kun 03.10.19 12:37:45 MSK
crutch_master ★★★★★
( 03.10.19 12:41:37 MSK )
Ответ на: комментарий от crutch_master 03.10.19 11:55:50 MSK

Мне в эмбедах не нравится, что каждый городит помойку собственных лисапедов. Скопипастить код не проблема, но хочется «красиво» - подключить зависимость в platformio или заюзать что-то готовое из стандартного.

Vit ★★★★★
( 03.10.19 13:01:37 MSK ) автор топика
Ответ на: комментарий от crutch_master 03.10.19 12:41:37 MSK

Это лишний раз доказывает, что флоат в имбеде нинужно!

shkolnick-kun ★★★★★
( 03.10.19 13:01:49 MSK )
Ответ на: комментарий от Vit 03.10.19 13:01:37 MSK

У тебя неправильные представления об этом всем.

Быстрее велосипед написать, чем заниматься поиском всякого нинужно на гитхабах

shkolnick-kun ★★★★★
( 03.10.19 13:02:36 MSK )
Последнее исправление: shkolnick-kun 03.10.19 13:03:29 MSK (всего исправлений: 1)

anonymous
( 03.10.19 13:08:14 MSK )
Ответ на: комментарий от anonymous 03.10.19 13:08:14 MSK

О, в ETL что-то есть на эту тему.

Vit ★★★★★
( 03.10.19 13:23:13 MSK ) автор топика
Ответ на: комментарий от crutch_master 03.10.19 11:55:50 MSK

Что там юзать? Сперва отсекаешь целое, потом берешь остаток, записываешь его в char* и делишь это целое в цикле на 10, пока не кончится. Дробную часть умножаешь на 10, пока не надоест, записывая целое в char*.

после взятия целого и остатка всё прочее лишнее. выводишь их как 16-тиричные, что почти моментально.. и получаешь результат аналогичный printf(«%a»,x) ..

может непривычно, но на то и эмбед. Зато кстати точность не теряется

MKuznetsov ★★★★★
( 03.10.19 17:02:08 MSK )
Ответ на: комментарий от MKuznetsov 03.10.19 17:02:08 MSK

Если ему так нужны флоаты, то, почему не сделать:

а) отдельно хранимые целое и дробное (как целое) и нужные функции по умножению, делению, сложению, вычитанию, выводу

б) условится, что целое меньше N разрядов (до нужной точности) — это дробная часть

deep-purple ★★★★★
( 03.10.19 17:15:57 MSK )

не то чтобы у меня дикий опыт в эмбедах, но он весь говорит что float на эмбедах это ошибка архитектуры. Замени float и уйдёт эта и куча другого не нужного хлама.

vtVitus ★★★★★
( 03.10.19 17:55:00 MSK )
Ответ на: комментарий от vtVitus 03.10.19 17:55:00 MSK

Ага, заодно еще посоветуй интерфейс превратить в кусок говна, как это принято на эмбедах. Потому что красивый интерфейс - это нарушение традиций.

Vit ★★★★★
( 03.10.19 18:15:25 MSK ) автор топика
Ответ на: комментарий от Vit 03.10.19 18:15:25 MSK

но ведь дело говорит. эмбеды обычно начинаются с определения числа значящих цифр, дальше сам догадаешся? хотя я выше уже питонячью обстракцию тебе кинул на подумать, видимо ты опять уперся

хм, не ну если ты только не калькулятор там пилишь (:

Morin ★★★★
( 03.10.19 18:47:58 MSK )
Последнее исправление: Morin 03.10.19 18:49:16 MSK (всего исправлений: 1)

Ответ на: комментарий от Morin 03.10.19 18:47:58 MSK

Нету там ни какого дела. Мог бы проект открыть, и посмотреть что там где я использую плавучку, кроилово нафик не уперлось. В интерфейсе важнее чтобы клепать быстро и менять легко.

А великие экономисты обычно лепят говнарские интерфейсы и просто не в состоянии представить, что иногда надо решать задачи поважнее экономии битов и тактов.

Vit ★★★★★
( 03.10.19 19:42:43 MSK ) автор топика
Ответ на: комментарий от Vit 03.10.19 19:42:43 MSK

ты сам наверху страдал по даблу, ну нельзя быть таким непоследовательным (: теперь оказывается ресурсы неважны

Morin ★★★★
( 03.10.19 20:04:45 MSK )

Есть, бери.

Могу посоветовать свой вариант d2a() , с тестом корректности и отдельным benchmark-ом.

По текущей информации это самая быстрая, компактная и корректная реализация d2a по мотивам алгоритма grisu. Ryu (пока) обгоняет её только потому, что я всегда генерирую полную строку (мне так надо было).

В бенчмарке собраны примерно все релевантные реализации d2a, поэтому можно посмотреть на альтернативы.

Функция d2a() преобразует double в корректную строку минимальной длины вида -22250738585072014e-324 , так чтобы обратное преобразование в double всегда дает исходное значение (но при этом, последняя цифра может быть +/-1 от оптимально близкой). Эту строку дальше можно легко превратить в желаемый формат.

Минусы: только double, код на C++, «сырой» формат результата (ничего лишнего, даже без \0 на конце).

Deleted
( 03.10.19 20:11:12 MSK )
Ответ на: комментарий от Morin 03.10.19 20:04:45 MSK

Не важны. Но мне не нравятся варнинги компилятора и есть желание поразбираться, как на сях лепить эмбеды дешево и сердито.

В общем я все динамические строки на ETL перевел. Годная штука.

Vit ★★★★★
( 03.10.19 20:12:17 MSK ) автор топика
Ответ на: Есть, бери. от Deleted 03.10.19 20:11:12 MSK

Спасибо. Я пока это заюзал https://www.etlcpp.com/to_string.html. Заодно будет повод в sdl поразбираться, сто лет уже на сях и плюсах не кодил.

Vit ★★★★★
( 03.10.19 20:26:51 MSK ) автор топика
Ответ на: комментарий от Vit 03.10.19 18:15:25 MSK

Ага, заодно еще посоветуй интерфейс превратить в кусок говна

«чую теоретика развитого социализма». ты бы с первых строк сказал, что твоё поделие «сферическое в вакууме», а то тебе помочь пытались исходя из опыта, а нужно исходить из красивых и не имеющих отношения к реальности картинок.

vtVitus ★★★★★
( 04.10.19 07:29:29 MSK )
Ответ на: комментарий от vtVitus 04.10.19 07:29:29 MSK

Зачем мне про себя что-то придумывать? Ссылку уже сто раз давал, видимо кроме тебя в танке больше никого не осталось. И таки да, совершенно не обязательно «пытаться мне помогать» по тем вопросам, где я совета не спрашивал.

Vit ★★★★★
( 04.10.19 07:37:09 MSK ) автор топика
Ответ на: комментарий от Vit 03.10.19 20:12:17 MSK

мда, походу в модеиаторы набрали полотеров, снесли все до кучи (:

Morin ★★★★
( 04.10.19 09:44:58 MSK )
Ответ на: комментарий от Morin 04.10.19 09:44:58 MSK

мда, походу в модераторы набрали полотеров, снесли все до кучи (:

Полотеры с синдромом вахтера? Горючая смесь!

anonymous
( 04.10.19 09:48:33 MSK )
Ответ на: комментарий от Morin 04.10.19 09:44:58 MSK

Без советов Эдика я переживу. Причем даже лучше чем с ними. Жалко что он сам это не хочет понимать.

Vit ★★★★★
( 04.10.19 11:01:15 MSK ) автор топика
Ответ на: комментарий от Vit 04.10.19 11:01:15 MSK

Он безвредный алкач, иногда буянит, но с него бывает толк

За последние несколько лет, что-то узнал с лора, всего от пары человек, персонаж один из них.

Увы лор много лет как, лор не является местом для решения проблем ни новичков, ни старожилов мира линукс

anonymous
( 04.10.19 11:06:13 MSK )
Ответ на: комментарий от anonymous 04.10.19 11:06:13 MSK

За последние несколько лет, что-то узнал с лора, всего от пары человек, персонаж один из них.

anonymous
( 04.10.19 11:08:53 MSK )
Ответ на: комментарий от Morin 04.10.19 09:44:58 MSK

фотачки второй версии платы воображаемого диспенсера 🙂

дисплейчик удачно воткнулся по размерам.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *