1

In c++ we have std::to_string which converts int/float/double to strings. So just to test my understanding of templates I tried the code below:

#include "iostream"
#include "sstream"
#include "string"
using std::cout;

template <typename T>
std::string getString(const T& data){
    std::stringstream ss;
    cout << '\n' << data << '\n';
    ss << data;
    std::string s;
    ss >> s;
    return s;
}

int main(int argc , char** argv){
    cout << getString(1.0000011);
    cout <<' '<<std::to_string(1.0000011);
    return 0;    
}

However, the output doesn't make sense, to_string gives me 1.0000011, whereas getString gets 1 and gives me 1. As I am using templates shouldn't getString get 1.0000011 as well and give me 1.0000011 too?

Arup
  • 384
  • 1
  • 10

3 Answers3

6

You can use std::setprecision in the <iomanip> header to set the precision that std::stringstream will use when formatting numeric data.

For example:

std::stringstream ss;
ss << std::setprecision(9) << data;
cout << ss.str();

Will print:

1.0000011

Here's a quick demo online: cpp.sh/9v7xf

As a side note, you don't have to create a string and output from the stringstream - you can replace the last 3 lines in getString() with:

return ss.str();
Chris Vig
  • 8,552
  • 2
  • 27
  • 35
2

Numeric values are often truncated for appearance. You can supply the std::fixed manipulator from the iomanip standard header to avoid this issue.

#include "iomanip" // <- Add this header
#include "iostream"
#include "sstream"
#include "string"
using std::cout;

template <typename T>
std::string getString(const T& data)
{
    std::stringstream ss;
    cout << '\n' << data << '\n';
    ss << std::fixed << data;
    //    ^^^^^^^^^^^^^ Add this
    std::string s;
    ss >> s;
    return s;
}

int main(int argc, char** argv)
{
    cout << getString(1.0000011);
    cout << ' ' << std::to_string(1.0000011);
    return 0;
}
François Andrieux
  • 28,148
  • 6
  • 56
  • 87
1

<iomanip> needs included, and std::setprecision must be used when outputting float values to streams. Using your example, this looks like:

#include <iostream>
#include <iomanip> //include this.
#include <sstream>
#include <string>

template <typename T>
std::string getString(const T& data){
    std::ostringstream ss;
    ss << std::setprecision(8);
    std::cout << std::setprecision(8);
    std::cout << data << '\n';
    ss << data;
    return ss.str();
}

int main(int argc , char** argv){
    std::cout << getString(1.0000011) << "\n";
    std::cout << std::to_string(1.0000011) << std::endl;
    return 0;
}

Which prints:

1.0000011
1.0000011
1.000001
Program ended with exit code: 0

Note how to_string alone truncates the floating point number!!! I suspect this is undesired behavior, but to_string cannot be manipulated directly, so...

If desired, you can fix this with the solution found here.

Otherwise, just use std:set_precision() when inserting into streams for precisely converted strings.

Community
  • 1
  • 1
NonCreature0714
  • 5,744
  • 10
  • 30
  • 52
  • I would use `std::ostringstream` instead. And you are using `std::setprecision()` only on `std::cout` but not on the `ss` stream as well. – Remy Lebeau Jan 11 '17 at 03:05
  • @Remy Lebeau , what is your reason for chosing std::ostringstream – Arup Jan 11 '17 at 05:56
  • 1
    @Arup `std::stringstream` is designed for both input and output, but `getString()` only needs output, which is what `std::ostringstream` is designed for. – Remy Lebeau Jan 11 '17 at 16:46