0

I have a double variable, the contents of which need to be converted into a string. I need to calculate, how long that string would end up being, so I tried using size(), but that leads to unexpected results.

From this:

double test_double;
test_double = 12.34;
std::wstring test_string = L"12.34";
std::wcout << L"string is: " << test_string << std::endl;
std::wcout << L"length of string is: " << test_string.size() << std::endl; //this shows expected result
std::wcout << L"double is: " << test_double << std::endl;
std::wcout << L"length of double is: " << (std::to_wstring(test_double)).size() << std::endl; //and this makes me wonder

I get this output:

string is: 12.34
length of string is: 5
double is: 12.34
length of double is: 9

The strings seem to end up being identical, but the result of a conversion is different for some reason. Am I missing something?

  • 5
    What do you get if you print the value of `std::to_wstring(test_double)`? – Daniel Aug 21 '23 at 17:05
  • 1
    [to_wstring](https://en.cppreference.com/w/cpp/string/basic_string/to_wstring) uses a default `%f` format, that probably results in `12.340000`. – BoP Aug 21 '23 at 17:08

1 Answers1

2

The documentation for std::to_wstring (https://en.cppreference.com/w/cpp/string/basic_string/to_wstring) states that it "Converts a floating point value to a wide string as if by std::swprintf(buf, sz, L"%f", value)".

If we look at the documentation for swprintf (https://en.cppreference.com/w/cpp/io/c/fwprintf) and look at the f format specifier, we see that it defaults to 6 digits of precision. This is leading to the string 12.340000.

std::cout is going to (by default) format doubles according to the defaultfloat IO manipulator described here: https://en.cppreference.com/w/cpp/io/manip/fixed. Importantly, you can see in their example that it will truncate zeroes and will thus produce 12.34 in this case.

When you explicitly convert to a string with std::to_wstring, you are now providing an explicit string to std::cout and so it doesn't try to be clever and truncate for you. When you give a double to std::cout, it has to make a decision as to what is the appropriate way to display the number (fixed digits, scientific, etc.). It turns out that the default behavior is simply not what you want in this case it seems.

Dean Johnson
  • 1,682
  • 7
  • 12
  • Thanks so much for the answer! I can see why all of this is happening now... But I cannot wrap my head around how to actually fix any of this. Is there a way to lower the precision for the conversion? – Anton Shustikov Aug 21 '23 at 18:08
  • 2
    If you have C++20 look at [std::format](https://en.cppreference.com/w/cpp/utility/format/format) it allows you to specify options for [formatting output](https://en.cppreference.com/w/cpp/utility/format/formatter#Standard_format_specification)) – Pepijn Kramer Aug 21 '23 at 18:17
  • 1
    If you do not have C++20, you could do what is described in this answer: https://stackoverflow.com/questions/16605967/set-precision-of-stdto-string-when-converting-floating-point-values. Clunky, but it works. Write a wrapper function. – Dean Johnson Aug 21 '23 at 18:27
  • You guys are a blessing, thank you all for your efforts! – Anton Shustikov Aug 21 '23 at 18:31