0

I want to convert float value i.e 3.14159267 in std::string I don't want to use sprintf

#include <iostream>   // std::cout
#include <string>     // std::string, std::to_string

int main ()
{
  std::string pi = "pi is " + std::to_string(3.14159267);
  std::cout<<pi<<std::endl;
  return 0;
}

I got result as 3.141593

Kirti Kedia
  • 133
  • 6
  • 2
    Well, you can't. You always loose some precision when converting between floats and decimal representations. – freakish Jan 25 '19 at 10:26
  • @freakish no you don't, if you do it right. – rubenvb Jan 25 '19 at 10:26
  • 2
    won't `stringstream` just handle this? – EdChum Jan 25 '19 at 10:26
  • And you can always put pi directlly to cout (or another stream) and increase display precision. – Matthieu Brucher Jan 25 '19 at 10:26
  • 1
    Dup targ isn't valid, the dup is about printing a full precision `double`. This question clearly prints out a string, so precision is lost because of `std::to_string`, not by `std::cout`. Reopening. – Hatted Rooster Jan 25 '19 at 10:28
  • See this question.. https://stackoverflow.com/questions/16605967/set-precision-of-stdto-string-when-converting-floating-point-values – Flo Jan 25 '19 at 10:44
  • You talk about not losing precision. That is tough. The number you want to have is "`3.14159267"` which you write down like a floating point number. Sadly this number is not representable as a floating point number. The closest IEEE 754 binary64 number (approximated as a decimal number) is `3.14159267000000008707161214260850101709365844726562...` So no matter what you do, you already lost your decimal precision from the start. Unless you state up to which precision you want the number to be equivalent. – kvantour Jan 25 '19 at 10:52
  • 1
    You probably do not understand the difference between a number and its representation. You should ask yourself “how many numbers are between any two numbers?”. – zdf Jan 25 '19 at 11:06
  • the float is coming from user input? I think it would help if you say why you need this and why you cant simply write `std::string pi = "3.14159267";`. Or is this really just about printing the float value? – 463035818_is_not_an_ai Jan 25 '19 at 11:09

3 Answers3

4

If you only want ot print out:

std::cout<< std::setprecision(9) << 3.14159267 << std::endl;

If you want to set the precision of string:

  double pi = 3.14159265359;
  std::stringstream stream;
  stream << std::setprecision(9) << pi;
  std::string pi_string = stream.str();
  std::cout<< "Pi:" << pi_string << std::endl;
Hubi
  • 1,629
  • 15
  • 20
  • I won't come to know what will be the length of the float value, thus I can't set the precision in advance. – Kirti Kedia Jan 25 '19 at 10:41
  • You do not need to know the length. Float has always a precision of 6. So you can leave that std::setprecisio out. By the way: your PI (3.14159267) needs double presicion – Hubi Jan 25 '19 at 10:54
  • Your first example may not work as expected because some stream manipulators are sticky and someone might have done `std::cout << std::fixed;` before this line. IMO, using `std::ostream` for number formatting is much subtler that it seems and too verbose. Try `std::cout << std::fixed << std::setprecision(9) << 0.000000000314159267 << '\n';` – Maxim Egorushkin Jan 25 '19 at 11:24
3

Theoretically, this should work with a C++17 compliant compiler (and is supposed to be fast and locale-independent):

#include <charconv>

const double pi = 3.14159267;
const int prec = 6;
char buffer[100];

auto [ptr, ec] = std::to_chars(buffer, std::end(buffer),
    pi, std::chars_format::fixed, prec);

Unfortunately, it doesn't, not even with the trunk version of gcc or clang. Seems that P0067R5 is not that obvious to implement, see also the cppreference compiler support (search for "P0067R5") or this reddit thread.

lubgr
  • 37,368
  • 3
  • 66
  • 117
2

I suggest you call snprintf with format specifier "%.16g" - that prints a double in decimal with 16 significant digits of precision. See Number of Digits Required For Round-Trip Conversions for more details. E.g.:

inline std::string as_string(double value) {
    char buf[32];
    return std::string(buf, std::snprintf(buf, sizeof buf, "%.16g", value));
}

*printf functions are fundamental conversion routines, everything else uses these.

std::to_string in GNU C++ standard library does:

inline string to_string(double __val)  {
  const int __n =  __gnu_cxx::__numeric_traits<double>::__max_exponent10 + 20;
  return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n, "%f", __val);
}

std::ostream also calls *snprintf under the hood to format numbers.


Also note that 3.14159267 is double. A float constant requires f suffix, e.g. 3.14159267f.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271